一、UDP是什么UDP 寄明信片写上地址IP端口就扔出去不保证对方一定能收到不保证顺序但速度很快对比TCP打电话特性TCP打电话UDP寄明信片连接要先拨号接通不用连接直接发可靠性可靠不丢包不可靠可能丢顺序保证顺序不保证效率较低高适用场景文件传输、网页视频直播、游戏二、UDP核心函数2.1 发送sendtointsendto(SOCKET s,// 套接字constchar*buf,// 要发的数据intlen,// 数据长度intflags,// 标志一般0constsockaddr*to,// 目标地址inttolen// 地址长度);2.2 接收recvfromintrecvfrom(SOCKET s,// 套接字char*buf,// 接收缓冲区intlen,// 缓冲区大小intflags,// 标志一般0sockaddr*from,// 发送方地址返回int*fromlen// 地址长度传入传出);三、UDP服务器代码详解#includeWinSock2.h#includeiostream#pragmacomment(lib,ws2_32.lib)intmain(){// 1. 初始化网络库 WORD wVersion;WSADATA wsaData;interr;wVersionMAKEWORD(1,1);// 请求1.1版本errWSAStartup(wVersion,wsaData);if(err!0)returnerr;// 检查版本if(LOBYTE(wsaData.wVersion)!1||HIBYTE(wsaData.wVersion)!1){WSACleanup();return-1;}// 2. 创建UDP套接字 // SOCK_DGRAM 表示UDP数据报SOCKET sockSrvsocket(AF_INET,SOCK_DGRAM,0);// 3. 绑定地址和端口 SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addrhtonl(INADDR_ANY);// 本机任意IPaddrSrv.sin_familyAF_INET;// IPv4addrSrv.sin_porthtons(6001);// 端口6001bind(sockSrv,(SOCKADDR*)addrSrv,sizeof(SOCKADDR));// 4. 循环接收和回复 SOCKADDR_IN addrCli;// 存放客户端地址intlensizeof(SOCKADDR_IN);charrecvBuf[100];charsendBuf[100];while(true){// 接收客户端数据// recvfrom会返回发送方的地址addrClirecvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)addrCli,len);// 打印收到的数据std::cout收到: recvBufstd::endl;// 构造回复sprintf_s(sendBuf,100,Ack %s,recvBuf);// 发送给刚才的客户端sendto(sockSrv,sendBuf,strlen(sendBuf)1,0,(SOCKADDR*)addrCli,len);}// 5. 清理 closesocket(sockSrv);WSACleanup();return0;}四、UDP客户端代码详解#includeWinSock2.h#includeiostream#pragmacomment(lib,ws2_32.lib)intmain(){// 1. 初始化网络库 WORD wVersion;WSADATA wsaData;interr;wVersionMAKEWORD(1,1);errWSAStartup(wVersion,wsaData);if(err!0)returnerr;if(LOBYTE(wsaData.wVersion)!1||HIBYTE(wsaData.wVersion)!1){WSACleanup();return-1;}// 2. 创建UDP套接字 SOCKET sockClisocket(AF_INET,SOCK_DGRAM,0);// 3. 设置服务器地址 SOCKADDR_IN addrSrv;addrSrv.sin_addr.S_un.S_addrinet_addr(127.0.0.1);// 本机addrSrv.sin_porthtons(6001);// 服务器端口addrSrv.sin_familyAF_INET;intlensizeof(SOCKADDR);charsendBuf[]hello;charrecvBuf[100];// 4. 发送数据 sendto(sockCli,sendBuf,strlen(sendBuf)1,0,(SOCKADDR*)addrSrv,len);// 5. 接收回复 // 注意这里addrSrv会被覆盖为发送方的地址recvfrom(sockCli,recvBuf,100,0,(SOCKADDR*)addrSrv,len);std::cout收到回复: recvBufstd::endl;// 6. 清理 closesocket(sockCli);return0;}五、UDP vs TCP 核心区别5.1 服务器端对比步骤TCP服务器UDP服务器1socket()socket()2bind()bind()3listen()❌ 不需要4accept()❌ 不需要5recv()/send()recvfrom()/sendto()5.2 客户端对比步骤TCP客户端UDP客户端1socket()socket()2connect()❌ 不需要3send()/recv()sendto()/recvfrom()5.3 关键区别TCP有连接// TCP必须先connectconnect(sock,...);send(sock,data,len,0);// 不用指定地址// 断开连接后就不能发了UDP无连接// UDP直接发每次都要指定地址sendto(sock,data,len,0,addr,sizeof(addr));// 可以给不同地址发sendto(sock,data1,len1,0,addr1,sizeof(addr1));sendto(sock,data2,len2,0,addr2,sizeof(addr2));六、UDP的特点详解6.1 无连接像寄信// UDP服务器一个套接字可以接收所有客户端的消息while(true){recvfrom(sock,buf,...,clientAddr,...);// 处理clientA的消息// 处理clientB的消息// 谁发来就处理谁}// TCP服务器每个客户端要单独的套接字client1accept(sock,...);client2accept(sock,...);// 每个客户端有自己的电话线6.2 不保证顺序// 发送顺序sendto(sock,A,...);// 先发Asendto(sock,B,...);// 后发B// 接收顺序可能是// 收到 B// 收到 A// 因为走不同的网络路径后发的可能先到6.3 不保证到达// 发送10个包for(inti0;i10;i){sendto(sock,data[i],...);}// 可能只收到8个// 2个在网络中丢了不会重传七、UDP适合做什么7.1 视频直播/会议// 丢几帧没关系流畅最重要while(hasFrame){sendto(sock,frame,...);// 直接发丢了就丢了}7.2 网络游戏// 玩家位置更新while(player.move()){sendto(sock,position,...);// 快速更新丢包无所谓}7.3 DNS查询// 发一个请求等一个回复sendto(sock,query,...);// 问www.baidu.com的IPrecvfrom(sock,reply,...);// 答220.181.38.1487.4 不适合的场景文件传输不能丢数据网页浏览必须完整邮件发送必须可靠八、UDP编程常见问题8.1 数据包大小限制// UDP包最大65507字节// 超过会失败charbigBuf[70000];sendto(sock,bigBuf,70000,...);// ❌ 可能失败8.2 接收缓冲区charrecvBuf[100];recvfrom(sock,recvBuf,100,...);// 最多收100字节// 如果对方发了200字节只会收前100剩下的丢了8.3 地址重用// UDP服务器可以同时被多个客户端发// 但一个端口只能被一个程序绑定UDP就像寄明信片不用提前打招呼无连接直接写上地址就扔出去sendto速度快但不保证能收到不可靠。适合视频直播、网络游戏这些可以忍受偶尔丢包的应用