UDP全称 User Datagram Protocol,即:用户数据报协议。是面向无连接的协议。通常,UDP 通信还会被冠以不可靠的头衔。这里的不可靠指的是:无法可靠地得知对方是否收到数据。
UDP有如下特征:
无连接:通信双方不需要事先连接
无确认:收到数据不给对方发回执确认
不保证有序、丢失不重发
采用帧同步的数据报通信方式(即通信双方每次的收发数据量相等)
简单来讲,UDP 类似于寄信,如果两个人除了信件之外没有任何别的通信方式,那么信件寄出去了之后,寄件人是无法得知收件人是否收到信件或者是否已经读取内容的。UDP 的特点是无需连接、无需确认、无需缓冲区和分包序列号,因此 UDP 的效率是比较高的。
UDP适用情况
发送小尺寸数据(如对DNS服务器进行IP地址查询时)
在接收到数据,给出应答较困难的网络中使用UDP。(如:无线网络)
广播、组播模式
即时通讯软件的点对点文本通讯以及音视频通讯
流媒体、VOD、VoIP、IPTV等网络多媒体服务中的实时数据传输
UDP通信流程
发送方:
创建 UDP 套接字: int fd = socket();
准备好接收方的地址:struct sockaddr_in peerAddr;
给对方发送 UDP 数据报:sendto(fd, peerAddr);
接收方:
创建 UDP 套接字:int fd = socket();
准备好自己的地址:struct sockaddr_in addr;
绑定套接字和地址:bind(fd, addr);
坐等各方发来的 UDP 数据报:recvfrom(fd);
代码
客户端
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
int main(){
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(1234);
while(1){
char buff[128] = {0};
fgets(buff, 128, stdin);
sendto(sockfd, buff, strlen(buff), 0, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
}
close(sockfd);
return 0;
}
服务端
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
int main(){
int sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
struct sockaddr_in serv_addr, clnt_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(1234);
bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
while(1){
char buff[128] = {0};
memset(buff, 0, sizeof(buff));
socklen_t len = (socklen_t)sizeof(clnt_addr);
int recv_size = recvfrom(sockfd, buff, sizeof(buff)-1, 0, (struct sockaddr*)&clnt_addr, &len);
char *ip = inet_ntoa(clnt_addr.sin_addr);
int port = ntohs(clnt_addr.sin_port);
printf("message from %s:%d,length:%d,context:%s\n", ip, port, recv_size, buff);
}
close(sockfd);
return 0;
}
