比比西旅游网站建设,设计邦中国官网,石家庄教育平台网站建设,网站设建设1 核心概念
1.1 UDP (User Datagram Protocol)
定义#xff1a;用户数据报协议。是一种无连接的、不可靠的、基于数据报的传输层协议。本质#xff1a;只负责把数据包扔出去#xff0c;不保证对方收到#xff0c;也不保证顺序。类似于“寄信”或“发短信”。特点#xff1…1 核心概念1.1 UDP (User Datagram Protocol)定义用户数据报协议。是一种无连接的、不可靠的、基于数据报的传输层协议。本质只负责把数据包扔出去不保证对方收到也不保证顺序。类似于“寄信”或“发短信”。特点无连接 (Connectionless)通信前不需要建立连接无三次握手结束时不需要断开无四次挥手。不可靠 (Unreliable)不提供重传、排序、流量控制机制。数据可能丢失、重复或乱序。面向数据报 (Datagram)保留数据边界。发送方发 100 字节接收方就得一次收 100 字节不会像 TCP 那样出现粘包。高效头部开销小仅 8 字节实时性高适合视频会议、直播、广播等场景。1.2 关键区别 (TCP vs UDP)特性TCP (打电话)UDP (发短信)连接性面向连接 (三次握手)无连接可靠性可靠 (重传、排序、校验)不可靠 (尽力而为)传输模式字节流 (Stream)数据报 (Datagram)Socket 类型SOCK_STREAMSOCK_DGRAM核心 APIread/writerecvfrom/sendto应用场景网页(HTTP)、文件传输(FTP)视频流、DNS、广播2 关键数据结构需包含头文件#include netinet/in.hUDP 使用与 TCP 完全相同的地址结构体没有区别。IPv4 专用地址结构体structsockaddr_in{shortintsin_family;// 地址族 (必须设为 AF_INET)unsignedshortintsin_port;// 端口号 (网络字节序, 使用 htons)structin_addrsin_addr;// IP 地址结构体unsignedcharsin_zero[8];// 填充字节 (置0)};structin_addr{unsignedlongs_addr;// 32位 IP 地址 (网络字节序)};3 核心 API需包含头文件#include sys/socket.h3.1 创建套接字intsocket(intdomain,inttype,intprotocol);type 使用SOCK_DGRAM(数据报套接字)。3.2 绑定地址 (bind)intbind(intsockfd,conststructsockaddr*addr,socklen_taddrlen);接收端 (Server)必须绑定。类似于在门口挂个信箱否则不知道收谁的信。发送端 (Client)通常不需要绑定。系统会自动分配一个临时端口发送数据。3.3 数据接收 (recvfrom)UDP 没有连接不知道数据从哪来所以接收时必须同时拿“信的数据”和“发信人的地址”。ssize_trecvfrom(intsockfd,void*buf,size_tlen,intflags,structsockaddr*src_addr,socklen_t*addrlen);功能接收数据并获取发送者的地址信息。参数src_addr(传出参数) 用来存储发送方的 IP 和端口信息。addrlen(传入传出参数)src_addr的长度。返回值成功返回接收到的字节数失败返回 -1。注意如果不关心是谁发的后两个参数可填NULL。3.4 数据发送 (sendto)UDP 没有连接发送时必须每次都指定“发给谁”。ssize_tsendto(intsockfd,constvoid*buf,size_tlen,intflags,conststructsockaddr*dest_addr,socklen_taddrlen);功能向指定的目标地址发送数据。参数dest_addr(传入参数)接收方的目标 IP 和端口结构体。addrlendest_addr的长度。返回值成功返回发送的字节数失败返回 -1。3.5 UDP 中通常不用listen()UDP 不需要监听因为没有连接请求。accept()UDP 不需要接受连接。connect()UDP 可以调用但含义不同变为“已连接 UDP”一般很少用。4 标准 UDP 编程模型阶段接收端 (Receiver/Server)发送端 (Sender/Client)1. 准备socket(..., SOCK_DGRAM, ...)socket(..., SOCK_DGRAM, ...)2. 地址填充sockaddr_in(本机 IP端口)填充sockaddr_in(目标 IP端口)3. 绑定bind()必须执行(通常省略系统自动分配)4. 通信recvfrom()(阻塞等待数据获取对方地址)sendto()(直接发送需指定目标地址)5. 回复sendto()(利用 recvfrom 得到的地址回复)recvfrom()(如果需要等待回复)6. 结束close()close()5. UDP Echo 实验代码5.1 接收端代码 (Server)负责接收数据打印发送者 IP并原样回传。#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includearpa/inet.h#includesys/socket.h#definePORT8888#defineBUFFER_SIZE1024intmain(){intsockfd;structsockaddr_inserv_addr,client_addr;charbuffer[BUFFER_SIZE];socklen_taddr_lensizeof(client_addr);// 1. 创建 UDP Socketif((sockfdsocket(AF_INET,SOCK_DGRAM,0))0){perror(socket);exit(1);}// 2. 绑定地址 (Server 必须 Bind)memset(serv_addr,0,sizeof(serv_addr));serv_addr.sin_familyAF_INET;serv_addr.sin_addr.s_addrINADDR_ANY;// 监听所有网卡serv_addr.sin_porthtons(PORT);if(bind(sockfd,(structsockaddr*)serv_addr,sizeof(serv_addr))0){perror(bind);exit(1);}printf([UDP Server] Listening on port %d...\n,PORT);while(1){memset(buffer,0,BUFFER_SIZE);// 3. 接收数据 (同时获取对方地址)intlenrecvfrom(sockfd,buffer,BUFFER_SIZE,0,(structsockaddr*)client_addr,addr_len);if(len0){buffer[len]\0;// 添加字符串结束符printf(Received from %s: %s\n,inet_ntoa(client_addr.sin_addr),buffer);// 4. 回复数据 (发回给 sender)sendto(sockfd,buffer,len,0,(structsockaddr*)client_addr,addr_len);}}close(sockfd);return0;}6.2 发送端代码 (Client)负责发送数据到指定 IP并等待回复。#includestdio.h#includestdlib.h#includestring.h#includeunistd.h#includearpa/inet.h#includesys/socket.h#defineSERVER_PORT8888#defineSERVER_IP192.168.7.2// 板子IPintmain(intargc,char*argv[]){intsockfd;structsockaddr_inserv_addr;charbuffer[1024];// 1. 创建 UDP Socketif((sockfdsocket(AF_INET,SOCK_DGRAM,0))0){perror(socket);exit(1);}// 2. 配置目标地址memset(serv_addr,0,sizeof(serv_addr));serv_addr.sin_familyAF_INET;serv_addr.sin_porthtons(SERVER_PORT);inet_pton(AF_INET,(argc1?argv[1]:SERVER_IP),serv_addr.sin_addr);while(1){printf(Input );fgets(buffer,sizeof(buffer),stdin);// 3. 发送数据 (指定发给 serv_addr)sendto(sockfd,buffer,strlen(buffer),0,(structsockaddr*)serv_addr,sizeof(serv_addr));// 4. 接收回复memset(buffer,0,sizeof(buffer));intlenrecvfrom(sockfd,buffer,sizeof(buffer),0,NULL,NULL);// 不关心是谁回的填NULLif(len0){buffer[len]\0;printf(Echo: %s\n,buffer);}}close(sockfd);return0;}