1 UDP通信过程
UDP客户端/服务器(C/S)结构的通信过程如下:
2 完整代码示例
server
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#define ERR_EXIT(m)\do\{\perror(m);\exit(EXIT_FAILURE);\}while(0)int main(){int sock;if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)//类型指定为数据报式,用于TCP{ERR_EXIT("socket create failed");}sockaddr_in servaddr;servaddr.sin_family = AF_INET;servaddr.sin_port = htons(5188);servaddr.sin_addr.s_addr = htonl(INADDR_ANY);//bind the socketif (bind(sock, (sockaddr*)&servaddr, sizeof(servaddr)) < 0){ERR_EXIT("bind socket failed");}//send and receive datachar recvbuf[1024] = {0};sockaddr_in remoteAddr;socklen_t remoteLen = sizeof(remoteAddr);int ret;while (1){memset(recvbuf, 0, sizeof(recvbuf));ret = recvfrom(sock, recvbuf, sizeof(recvbuf), 0, (sockaddr*)&remoteAddr, &remoteLen);if (ret == -1){if (errno == EINTR)continue;//是系统中断导致,则继续ERR_EXIT("recvfrom failed");}else if (ret > 0){printf("%s\r\n", recvbuf);sendto(sock, recvbuf, ret, 0, (sockaddr*)&remoteAddr, remoteLen);}}close(sock);}
client
#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#include <string.h>#include <arpa/inet.h>#define ERR_EXIT(m)\do\{\perror(m);\exit(EXIT_FAILURE);\}while(0)int main(){int sock;if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)//类型指定为数据报式,用于TCP{ERR_EXIT("socket create failed");}sockaddr_in servaddr;servaddr.sin_family = AF_INET;servaddr.sin_port = htons(5188);servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");//指定server地址//send and receive datachar sendbuf[1024] = {0};int ret;while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL){sendto(sock, sendbuf, strlen(sendbuf), 0, (sockaddr*)&servaddr, sizeof(servaddr));memset(sendbuf, 0, sizeof(sendbuf));ret = recvfrom(sock, sendbuf, sizeof(sendbuf), 0, NULL, NULL);//从server接收,不需要指定ipif (ret == -1){if (errno == EINTR)continue;//是系统中断导致,则继续ERR_EXIT("recvfrom failed");}else if (ret > 0){printf("%s\r\n", sendbuf);memset(sendbuf, 0, sizeof(sendbuf));}}close(sock);}
3 UDP的注意点
- UDP报文可能会丢失或重复
- UDP报文可能会乱序
- UDP缺乏流量控制,缓冲区数据可能被覆盖
- UDP数据报文可能被截断
- recvfrom返回0,不代表连接关闭,因为UDP是无连接的
- ICMP异步错误,本端无法知道对端是否开启,发生数据不会出现错误提示(可以先调用一下UDP connect函数,这样发送数据会返回错误)
