一、定义与值
- 头文件:定义在 <netinet/in.h>(Linux/Unix)或 <winsock2.h> (windows)中:
#define IPPROTO_UDP 17 /* UDP 协议 */
- 值:17 ,对应IANA分配的UDP协议号(IANA协议号列表)
- 层级:属于传输层协议(OSI第四层),基于IP协议(网络层)工作
二、核心作用
1. 标识UDP协议
- 在套接字编程中,指定使用UDP协议进行数据传输
- 在IP数据包头部中,Protocol字段值为17时,标识负载时UDP数据报
2. 启用UDP特性
特性 | 说明 |
无连接 | 无需预先建立连接,直接发送数据。 |
不可靠传输 | 不保证数据到达顺序、不重传丢失包、无流量控制。 |
低延迟 | 协议头部简单(仅 8 字节),适合实时性要求高的场景。 |
支持广播/组播 | 可向多个目标同时发送数据(如局域网广播)。 |
三、实际应用场景
1. 实时音视频传输
- 视频会议、在线直播等场景中,少量丢包对体验影响较小,但低延迟至关重要
- 示例:Zoom/Skype使用UDP传输音视频流,配合前向纠错(FEC降低丢包影响)
2. DNS查询
- DNS协议默认使用UDP,单次请求-响应模型简单高效
- 示例:查询example.com的IP地址时,客户端通过UDP发送请求到DNS服务器的53端口
3. 物联网设备通信
- 传感器数据上报通常频率高、数据量小,UDP的资源消耗更低
- 示例:智能家居设备定期发送温湿度数据到服务器
4. 网络游戏
- 多玩家实时位置同步需要低延迟,偶尔丢包可通过逻辑层容错
- 示例:FPS游戏(如CS:GO)使用UDP传输玩家动作和位置
四、UDP数据报格式
字段 | 长度(字节) | 说明 |
源端口(Source Port) | 2 | 发送方端口号(可选,可为 0 )。 |
目标端口(Dest Port) | 2 | 接收方端口号。 |
长度(Length) | 2 | UDP 头部 + 数据的总长度(最小为 8)。 |
校验和(Checksum) | 2 | 数据完整性校验(可选,IPv4 中可置 0 )。 |
五、常见协议号对比
常量 | 值 | 协议 | 特性 |
IPPROTO_UDP | 17 | UDP | 无连接、不可靠、低延迟。 |
IPPROTO_TCP | 6 | TCP | 可靠、面向连接、流量控制。 |
IPPROTO_ICMP | 1 | ICMP | 网络层错误与控制消息(如 ping)。 |
六、代码示例
1. 创建UDP服务器(C语言)
#include <sys/socket.h>
#include <netinet/in.h>int main() {// 创建 UDP 套接字int sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);struct sockaddr_in addr;addr.sin_family = AF_INET;addr.sin_port = htons(8080);addr.sin_addr.s_addr = INADDR_ANY;// 绑定端口bind(sock, (struct sockaddr *)&addr, sizeof(addr));// 接收数据char buffer[1024];struct sockaddr_in client_addr;socklen_t addr_len = sizeof(client_addr);recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *)&client_addr, &addr_len);// 发送响应sendto(sock, "Response", 8, 0, (struct sockaddr *)&client_addr, addr_len);return 0;
}
2. 发送UDP数据(Python)
import socket# 创建 UDP 套接字
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)# 发送数据到目标地址
sock.sendto(b"Hello UDP!", ("example.com", 8080))# 接收响应(可选)
response, addr = sock.recvfrom(1024)
print(f"Received from {addr}: {response.decode()}")
sock.close()
七、注意事项
1. 数据完整性
- UDP不提供重传机制,需应用层自行处理丢包(如添加序列号、超时重传)
- 校验和:在IPv4中可选,但在IPv6中强制启用
2. 缓冲区管理
- UDP不维护发送/接收缓冲区,应用需控制发送速率,避免接收方溢出:
// 设置接收缓冲区大小
int buffer_size = 1024 * 1024;
setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &buffer_size, sizeof(buffer_size));
3. 防火墙与NAT:
- UDP无连接状态,某些防火墙可能默认拦截UDP流量,需显式放行端口
- NAT设备对UDP会话的过期时间较短(通常30~120秒),长时间空闲可能导致映射失效
4. 组播与广播
- 使用setsockopt启用组播
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr("239.255.255.250");
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
八、总结
- 本质:标识UDP协议的常量(协议号=17)
- 用途:
- 在传输层启用UDP的高效无连接传输
- 在套接字编程中显式指定UDP协议
- 关键特性:无连接、低开销、支持广播/组播
- 适用场景:实时应用、高频小数据量通信、广播/组播需求