当前位置: 首页 > news >正文

华清远见25072班网络编程学习day2

重点内容:

一、套接字通信        

socket函数:

        int socket(int domain, int type, int protocol);

        功能:为通信方提供一个通信端点,并返回控制该端点的文件描述符(最小未使用原则)

        参数1:通信域(使用系统提供的宏值)

                AF_UNIX, AF_LOCAL 同一主机间的多个进程的通信 详情请看 man 7 unix

                AF_INET 提供ipv4的通信协议 详情请看 man 7 ip

                AF_INET6 提供ip v6的通信协议 详情请看 man 7 ipv6

        参数2:通信语义(通信方式)

                SOCK_STREAM 提供TCP的通信方式

                SOCK_DGRAM 提供UDP的通信方式

        参数3:如果参数2中唯一指定的一种通信方式,那么该参数填0

        返回值:成功返回一个新的用于控制套接字的文件描述符,失败返回-1并置位错误码

eg:

        创建TCP通信端点:int sfd = socket(AF_INET, SOCK_STREAM, 0)

        创建UDP通信端点:int sfd = socket(AF_INET, SOCK_DGRAM, 0)

二、基于TCP的通信

原理图

bind函数

        int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

        功能:为套接字绑定地址空间

        参数1:要被绑定的套接字文件描述符

        参数2:是一个通用地址信息结构体,该结构体的目的是为了将实际的结构体地址强制类型转换,防止编译器警告的,实际的结构体取决于地址族

对于AF_UNIX、AF_LOCAL:而言

struct sockaddr_un {

        sa_family_t sun_family;         /* AF_UNIX */

        char sun_path[108];               /* pathname */

};

对于AF_INET而言:

struct sockaddr_in {

        sa_family_t sin_family;           /* address family: AF_INET */

        in_port_t sin_port;                  /* 端口号的网络字节序 */

        struct in_addr sin_addr;         /* internet address */

};

/* Internet address. */

struct in_addr { uint32_t s_addr; /* ip地址的网络字节序 */ };

        参数3:就是参数2的大小

        返回值:成功返回0,失败返回-1并置位错误码

listen函数

        int listen(int sockfd, int backlog

        功能:将套接字设置成监听状态,注意,只有面向连接的套接字,才能启动监听

        参数1:要被设置成监听的套接字文件描述符

        参数2:未连接队列的大小,一般为128,也就是一次性处理连接的个数

        返回值:成功返回0,失败返回-1并置位错误码

accept函数

        int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

        功能:阻塞等待客户端的连接请求,如果有新的客户端发来连接请求,那么会解除阻塞,并创建一个用于通信的套接字文件描述符

        参数1:服务器的套接字文件描述符

        参数2:用于接收客户端地址信息的结构体,传递一个结构体变量的地址,如果不想接收对方地址信息,填NULL即可

        参数3:用于接收对方地址信息结构体的大小,如果参数2填NULL,那么参数3也是NULL

        返回值:成功返回一个创建出来的用于通信的套接字文件描述符(最小未分配原则),失败返回-1并置位错误码

connect函数

        int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);

        功能:将套接字连接到对端

        参数1:套接字文件描述符

        参数2:对端地址信息结构体

        参数3:参数2的大小

        返回值:成功返回0,失败返回-1并置位错误码

三、基于UDP通信

原理图

sendto函数

        ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);

        功能:从sockfd文件描述符中发送buf作为起始地址的消息,一共发送len的长度,给dest_addr指向的地址中

        参数1:发送消息端的套接字文件描述符

        参数2:要发送的消息的起始地址

        参数3:要发送的数据长度

        参数4:是否以阻塞的形式发送 0:表示阻塞 MSG_DONTWAIT:表示非阻塞

        参数5:要发送的数据对端地址信息结构体

        参数6:参数5的大小

        返回值:成功返回本次发送的字节数,失败返回-1并置位错误码

recvform函数:

        ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);

        功能:从sockfd套接字文件描述符中读取长度为len的数据,放入到buf作为起始地址的容器中,并且可以接收对端地址信息

        参数1:接收消息的套接字文件描述符

        参数2:存放接收消息的容器的起始地址

        参数3:参数2的大小

        参数4:是否阻塞接受 0:表示阻塞 MSG_DONTWAIT:表示非阻塞

        参数5:用于接受对端地址信息的结构体

        参数6:参数5的大小

        返回值:

                如果成功接收了消息,那么返回的是消息的总字节数,当然也可以接收长度为0的字符串,并不代表这对端已经下线

                如果以非阻塞形式接受消息,但是并没有任何消息收到时,也会返回0 失败返回-1并置位错误码


作业:

1> TCP和UDP通信

TCP通信:

程序源码:

01tcpser.c

#include <25072head.h>
#define SER_IP "192.168.153.128"  //服务器ip地址
#define SER_PORT 8888             //服务器端口号
int main(int argc, const char *argv[])
{
//1.创建一个用于连接的套接字文件描述符
int sfd=socket(AF_INET,SOCK_STREAM,0);
if(sfd==-1)
{
perror("socket error");
return -1;
}
printf("sfd=%d\n",sfd);
//2.给套接字绑定ip地址和端口号
//2.1准备地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;    //通信域地址族
sin.sin_port=htons(SER_PORT);   //服务器端口号
sin.sin_addr.s_addr=inet_addr(SER_IP); //服务器ip地址

    //2.2执行绑定工作
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
printf("bind success\n");
//3.将套接字设置成被动监听状态
if(listen(sfd,128)==-1)
{
perror("listen error");
return -1;
}
printf("listen success\n");
//4.阻塞等待客户端的连接
//4.1定义地址信息结构体,用于接收客户端地址信息
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
int newfd=accept(sfd,(struct sockaddr*)&cin,&addrlen);
if(newfd==-1)
{
perror("accept error");
return -1;
}
printf("[%s:%d]-连接成功了newfd = %d\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),newfd);
//5.实现数据的收发
char buf[128]="";
while(1)
{
//清空buf
bzero(buf,sizeof(buf));
//从套接字中读取消息
int res=read(newfd,buf,sizeof(buf));
if(res==0)
{
printf("客户端已下线\n");
close(newfd);
return -1;
}
printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);
strcat(buf,"*_*");
write(newfd,buf,strlen(buf));
}
close(sfd);
return 0;
}

02tcpcli.c

#include <25072head.h>
#define SER_IP "192.168.153.128"  //服务器ip地址
#define SER_PORT 8888             //服务器端口号
#define CLI_IP "192.168.153.128"  //服务器ip地址
#define CLI_PORT 7777             //服务器端口号

int main(int argc, const char *argv[])
{
//1.创建一个用于连接的套接字文件描述符 
int cfd=socket(AF_INET,SOCK_STREAM,0);
if(cfd==-1)
{
perror("socket error");
return -1;
}
//2.给客户端套接字绑定ip地址和端口号
//2.1填充地址信息结构体
struct sockaddr_in cin;
cin.sin_family=AF_INET;
cin.sin_addr.s_addr=inet_addr(CLI_IP);
cin.sin_port=htons(CLI_PORT);
if(bind(cfd,(struct sockaddr*)&cin,sizeof(cin))==-1)
{
perror("bind error");
return -1;
}
//3.链接服务器
//3.1组装对端地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;    //通信域地址族
sin.sin_port=htons(SER_PORT);   //服务器端口号
sin.sin_addr.s_addr=inet_addr(SER_IP); //服务器ip地址
//3.2连接操作
if(connect(cfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("connect error");
return -1;
}
//4.数据通信
char buf[128]="";
while(1)
{
//从终端输入要发送的消息
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]=0;
//判断输入内容
if(strcmp(buf,"quit")==0)
{
break;
}
//将消息发送给服务器
write(cfd,buf,strlen(buf));
printf("发送成功\n");
//接受服务器发来的消息
bzero(buf,sizeof(buf));
int res=read(cfd,buf,sizeof(buf));
if(res==0)
{
printf("服务器已下线\n");
break;
}
printf("收到服务器消息:%s\n",buf);
}
//5.关闭套接字
close(cfd);
return 0;
}

UDP通信:

03udpser.c

#include <25072head.h>
#define SER_IP "192.168.153.128"  //服务器ip地址
#define SER_PORT 8888             //服务器端口号
int main(int argc, const char *argv[])
{
//1.创建一个用于通信的套接字文件描述符
int sfd=socket(AF_INET,SOCK_DGRAM,0);
if(sfd==-1)
{
perror("socket error");
return -1;
}
//2.给套接字绑定ip地址和端口号
//2.1封装地址信息结构体
struct sockaddr_in sin;
sin.sin_family=AF_INET;    //通信域地址族
sin.sin_port=htons(SER_PORT);   //服务器端口号
sin.sin_addr.s_addr=inet_addr(SER_IP); //服务器ip地址

    //2.2执行绑定工作
if(bind(sfd,(struct sockaddr*)&sin,sizeof(sin))==-1)
{
perror("bind error");
return -1;
}
//3.数据收发
char buf[128]="";
struct sockaddr_in cin;
socklen_t addrlen=sizeof(cin);
while(1)
{
//清空容器
bzero(buf,sizeof(buf));
recvfrom(sfd,buf,sizeof(buf),0,(struct sockaddr*)&cin,&addrlen);
printf("[%s:%d]:%s\n",inet_ntoa(cin.sin_addr),ntohs(cin.sin_port),buf);
strcat(buf,"*_*");
sendto(sfd,buf,strlen(buf),0,(struct sockaddr*)&cin,sizeof(cin));
printf("发送成功\n");
}
//关闭套接字
close(sfd);

    return 0;
}

04udpcli.c

#include <25072head.h>
#define SER_IP "192.168.153.128"
#define SER_PORT 8888
int main(int argc, const char *argv[])
{
//1.创建一个用于通信的套接字文件描述符
int cfd = socket(AF_INET, SOCK_DGRAM, 0);
if(cfd == -1)
{
perror("socket error");
return -1;
}

    //2.绑定ip和端口号(可选)
//3.数据收发
char buf[128] = "";    //数据容器
struct sockaddr_in sin;     //目标地址
sin.sin_family = AF_INET;
sin.sin_port = htons(SER_PORT);
sin.sin_addr.s_addr = inet_addr(SER_IP);
socklen_t addrlen = sizeof(sin);
while(1)
{
//清空容器
bzero(buf, sizeof(buf));
fgets(buf, sizeof(buf), stdin);   //从终端获取数据
buf[strlen(buf)-1] = 0;
if(strcmp(buf,"quit")==0)
{
break;
}
//将数据发送给服务器
sendto(cfd, buf, strlen(buf), 0, (struct sockaddr*)&sin, sizeof(sin));
printf("发送成功\n");
//接收服务器发来的消息
bzero(buf, sizeof(buf));
//recvfrom(cfd, buf, sizeof(buf), 0, (struct socket*)&sin, &addrlen);
//recvfrom(cfd, buf, sizeof(buf), 0, NULL,NULL);
read(cfd, buf, sizeof(buf));
printf("收到服务器消息为:%s\n", buf);
}
//4.关闭套接字
close(cfd);
return 0;
}

2> 牛客网

3>思维导图


文章转载自:

http://3Cqiybsi.yLtnL.cn
http://Vw91WShM.yLtnL.cn
http://STFQI1Q7.yLtnL.cn
http://Bv2kbfAl.yLtnL.cn
http://gjSsAaGe.yLtnL.cn
http://VC1oaZ7w.yLtnL.cn
http://3Ek8myjl.yLtnL.cn
http://yUkv9dJG.yLtnL.cn
http://2Icj1qhg.yLtnL.cn
http://fs0DuXcZ.yLtnL.cn
http://S3gxMYMI.yLtnL.cn
http://ptA5lDaf.yLtnL.cn
http://SvtbBDcH.yLtnL.cn
http://sUapBCmO.yLtnL.cn
http://71bsYTBm.yLtnL.cn
http://G3p8AbYP.yLtnL.cn
http://24tNRNXY.yLtnL.cn
http://lKDzJ0Vf.yLtnL.cn
http://fpA2BMo2.yLtnL.cn
http://CPYvPjiC.yLtnL.cn
http://Ian8sjsZ.yLtnL.cn
http://jL0Gn4s6.yLtnL.cn
http://NXDlmnqd.yLtnL.cn
http://tggcm6oN.yLtnL.cn
http://5QpwF1k6.yLtnL.cn
http://F2D5BxaR.yLtnL.cn
http://AQI9AFV1.yLtnL.cn
http://BapX0B6I.yLtnL.cn
http://J6oZfpa9.yLtnL.cn
http://Sz3WP0w9.yLtnL.cn
http://www.dtcms.com/a/375852.html

相关文章:

  • 【论文写作】--网络与信息安全顶刊顶会
  • 【人工智能99问】如何基于QWen3进行LoRA微调?(38/99)
  • JAVA Predicate
  • 自动驾驶中的传感器技术41——Radar(2)
  • Netty HandlerContext 和 Pipeline
  • Stuns in Singapore!中新赛克盛大亮相ISS World Asia 2025
  • 开始 ComfyUI 的 AI 绘图之旅-LoRA(五)
  • 字符函数和字符串函数 last part
  • win安装多个mysql,免安装mysql
  • 开源项目_强化学习股票预测
  • Shell 脚本基础:从语法到实战全解析
  • Nginx如何部署HTTP/3
  • 解一元三次方程
  • A股大盘数据-20250909分析
  • 05-Redis 命令行客户端(redis-cli)实操指南:从连接到返回值解析
  • shell函数+数组+运算+符号+交互
  • 群晖Lucky套件高级玩法-——更新证书同步更新群晖自带证书
  • 照明控制设备工程量计算 -图形识别超方便
  • Matlab通过FFT快速傅里叶变换提取频率
  • iis 高可用
  • 有趣的数学 贝塞尔曲线和毕加索
  • 基于STM32的智能宠物小屋设计
  • STM32之RS485与ModBus详解
  • DCDC输出
  • GitHub 项目提交完整流程(含常见问题与解决办法)
  • Day39 SQLite数据库操作与文本数据导入
  • python常用命令
  • 广东省省考备考(第九十五天9.9)——言语、资料分析、判断推理(强化训练)
  • MySQL问题8
  • 【AI】Jupyterlab中关于TensorFlow版本问题