一、什么是UDP
Internet协议集支持一个无连接的传输协议,该协议称为用户数据报协议(UDP,User Datagram Protocol)。UDP 为应用程序提供了一种无需建立连接就可以发送封装的 IP 数据包的方法。
Internet 的传输层有两个主要协议,互为补充。无连接的是 UDP,它除了给应用程序发送数据包功能并允许它们在所需的层次上架构自己的协议之外,几乎没有做什么特别的事情。面向连接的是 TCP,该协议几乎做了所有的事情。
二、UDP的特点
1、服务器与客户端之间无需建立链接
2、只需要知道对方的套接字信息,就可以发送数据
3、服务器只需要创建一个套接字来接收不同客户端发来的请求,处理过后发送给对应的客户端
三、UDP创建的框架
四、相关函数
由于此前在TCP中我们已经讲过除recvfrom和sendto之外的函数,所以这里我们主要讲解recvfrom和sendto函数。
如果之前没有观看过的小伙伴,可以点击下方链接查看相关函数功能:
https://blog.csdn.net/m0_45901455/article/details/126353742?spm=1001.2014.3001.5501
1、接收数据——recvfrom()
函数原型:
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags, struct sockaddr *src_addr, socklen_t *addrlen);
功能:
接收数据
参数:
sockfd: socket函数的返回值数据报套接字
buf:内存地址 len: 接收数据的大小
flags:0
src_addr: 发送端的结构体的地址
addrlen: 发送端的结构体长度的地址
返回值:
成功:返回接收的字节数
失败:-1
2、发送数据——send()
函数原型:
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags, const struct sockaddr *dest_addr, socklen_t addrlen);
功能:
发送数据
参数:
sockfd: socket函数的返回值数据报套接字
buf:内存地址
len: 接收数据的大小
flags:0
dest_addr: 接收端的结构体的地址
addrlen: 接收端的结构体长度
返回值:
成功:返回发送的字节数
失败:-1
5、代码案例
此处我们只进行客户端数据的发送和服务器数据的接收
1、服务器创建代码
/*=============================================================== * Copyright (C) 2022 All rights reserved. * * 文件名称:server.c * 创 建 者:QiuCC * 创建日期:2022年08月17日 * 描 述: * * 更新日志: * ================================================================*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> #include <netinet/ip.h> #define N 100 int main(int argc, char *argv[]) { //创建服务器套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd < 0) { perror("创建服务器套接字"); exit(-1); } //保存服务器信息,结构体创建 struct sockaddr_in serveaddr, cilentaddr; //1、协议族 serveaddr.sin_family = AF_INET; //2、端口号 serveaddr.sin_port = htons(7777); //3、ip地址 serveaddr.sin_addr.s_addr = inet_addr("0"); //绑定套接字 if( bind(sockfd, (struct sockaddr *)&serveaddr, sizeof(serveaddr)) < 0 ) { perror("绑定套接字"); exit(-1); } printf("接收方IP信息为:%s,端口号为:%d\n", inet_ntoa(serveaddr.sin_addr), ntohs(serveaddr.sin_port)); //发送端结构体大小,取地址作为recvfrom参数 int size = sizeof(cilentaddr); //收发数据 char buf[N] = {0}; while(1) { int ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&cilentaddr, &size); if(ret < 0) { perror("接收"); exit(-1); } printf("发送方IP信息为:%s,端口号为:%d\n", inet_ntoa(cilentaddr.sin_addr), ntohs(cilentaddr.sin_port)); printf("%s发送信息为:%s\n", inet_ntoa(cilentaddr.sin_addr), buf); memset(buf, 0, N); } //关闭服务器套接字 close(sockfd); return 0; }
2、客户端创建代码
/*=============================================================== * Copyright (C) 2022 All rights reserved. * * 文件名称:server.c * 创 建 者:QiuCC * 创建日期:2022年08月17日 * 描 述: * * 更新日志: * ================================================================*/ #include <stdio.h> #include <string.h> #include <stdlib.h> #include <strings.h> #include <sys/types.h> #include <unistd.h> #include <netinet/ip.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <arpa/inet.h> #define N 100 int main(int argc, char *argv[]) { if(argc < 2) { printf("请输入:<./a.out> <服务器ip>\n"); exit(-1); } //创建客户端套接字 int sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd < 0) { perror("创建客户端套接字"); exit(-1); } //创建接收端的结构体信息 struct sockaddr_in serveraddr; //接收端结构体大小,作为sendto的最后一个参数 int size = sizeof(serveraddr); //收发数据 char buf[N] = {0}; while(1) { sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&serveraddr, size); } //关闭客户端套接字 close(sockfd); return 0; }
6、结果分析
1、首先我们使用ifconfig指令获取当前主机的IP地址作为服务器地址
2、我们开启服务器
3、开启客户端(由于我们将argv[1]用来存储IP地址,所以需要用到第一步的IP)
4、输入多个数据进行测试
(1)客户端
(2)服务器
5、关闭客户端
此时可以发现,我们的客户端关闭并没有对服务器造成影响,所以UDP是建立连接的。
6、手动关闭服务器
通过以上测试步骤可以发现UDP服务器与客户端之间是相互独立的,关闭客户端对服务器是没有影响的,客户端关闭之后重新连接也是可行的,并且,我们可以同时连接多个客户端进行通信,由于此处设备不足,所以我们只进行了小部分操作,感兴趣的同学也可以自己和你的朋友试一下!!!
好的,以上就是本期内容,欢迎大家参考、指正!!!