UDP 实战与排错 — 抓包、设计与故障定位
UDP Wireshark 抓包、应用层重传/超时设计、udp 丢包/截断排查、与 TCP 对比 / 传输层 / RFC 768
这篇你能学到
- 用 Wireshark / tcpdump 把 UDP 流量按端口、按包长挑出来,并识别分片黑洞的信号。
- UDP 应用必须自己补上的东西(超时重传、序列号、ACK),以及查看监听端口、接收错误、调大缓冲的命令。
- 六类常见故障(收端丢包、大包发不到、收不全、NAT 后无回包、端口不可达、数据"粘连")的结论先行式排查,外加对比表和面试速查。
1. 抓包观察
下面这些过滤式的作用:先把 UDP 流量整体捞出来或按端口聚焦,再重点盯住"接近 MTU 的大包"和"PMTUD 的 ICMP 回包"——UDP 的疑难杂症有相当一部分都出在包太大上。
| 过滤式 | 作用 |
|---|---|
udp / ip.proto == 17 | 所有 UDP |
udp.port == 53 | 指定端口(如 DNS) |
udp.length > 1400 | 接近/超过常见 MTU 的大包(易分片丢) |
icmp.type == 3 && icmp.code == 4 | PMTUD,排查 UDP 分片黑洞 |
这两条命令:第一条带绝对时间戳实时看 DNS 流量,适合观察请求-响应的时间间隔;第二条把全部 UDP 完整落盘成 pcap,事后慢慢分析。
Wireshark 中 Follow → UDP Stream 重组同组数据报;关注 Length、Checκsum status、是否分片(IP fragmentation)。
2. 常用设计 / 命令
这段内容做的事:前半部分是一个最小的 UDP echo 服务器骨架(绑定端口、循环 recvfrom 收一整条、原样加前缀回送),用来直观体会"一次收一条"的消息边界;后半部分是系统侧观测与调优——查看监听中的 UDP 端口、查看内核记录的 UDP 接收错误计数、以及调大接收缓冲上限防止收端丢包。
| |
3. 常见故障与排错
现象:收端丢包
先记住结论: 包其实到了机器上,是在内核收到、应用没来得及取这一步被丢的——接收缓冲满了或应用处理太慢。
排查/解决:netstat -su 看 receive errors;增大 rmem_max;应用尽快消费。
现象:大包发不到
先记住结论: 小包能过大包不行,基本可以锁定 MTU 分片黑洞——DF 置位或中间设备把分片丢了。
排查/解决:把单 datagram 控制在 ≤1400B;必要时 dont-fragment 探测。
现象:偶尔收不全
先记住结论: 一条 datagram 被拆成多个分片,只要丢一片整条就废,所以表现为时好时坏。
排查/解决:应用层分片重传,或限制包长。
现象:NAT 后收不到回包
先记住结论: 不是对方没回,是 NAT 上那条映射表项已经超时被回收了——UDP 无连接,NAT 只能靠计时器猜。
排查/解决:缩短心跳间隔保 NAT 表项;用 STUN 打洞。
现象:端口不可达
先记住结论: 对端机器活着但那个端口上没有服务在听。
排查/解决:ICMP Port Unreachable;确认服务已起。
现象:数据"粘在一起"
先记住结论: 这锅不在 UDP——UDP 本身保留消息边界,是接收端读法不对或发送端自己把多条拼成了一条。
排查/解决:UDP 本身有边界,确认接收端按 datagram 读。
| 现象 | 原因 | 排查/解决 |
|---|---|---|
| 收端丢包 | 接收缓冲满/处理慢 | netstat -su 看 receive errors;增大 rmem_max;应用尽快消费 |
| 大包发不到 | MTU 分片黑洞:DF 或中间丢分片 | 把单 datagram 控制在 ≤1400B;必要时 dont-fragment 探测 |
| 偶尔收不全 | 部分分片丢失整包失败 | 应用层分片重传,或限制包长 |
| NAT 后收不到回包 | 无连接,NAT 表项超时 | 缩短心跳间隔保 NAT 表项;用 STUN 打洞 |
| 端口不可达 | 对端未监听 | ICMP Port Unreachable;确认服务已起 |
| 数据"粘在一起" | 误用流式 API / 自己拼包 | UDP 本身有边界,确认接收端按 datagram 读 |
4. 与其他协议对比
| 维度 | UDP | TCP | QUIC(over UDP) |
|---|---|---|---|
| 连接 | 无 | 有 | 有(在 UDP 上) |
| 可靠 | 否 | 是 | 是(自实现) |
| 消息边界 | 有 | 无 | 有(流内) |
| 头部 | 8B | 20+B | 8B + 自身帧 |
| 加密 | 无 | 无(靠 TLS) | 内建 |
| 队头阻塞 | 无(独立 datagram) | 有 | 流级隔离 |
5. 速查表 / 常见面试题
| 项目 | 值 |
|---|---|
| RFC / IP 协议号 | RFC 768 / 17 |
| 头部长度 | 8 字节 |
| 最大载荷 | 65507 字节 |
| 校验和 | IPv4 可选,IPv6 必填 |
| 典型端口 | DNS 53 / DHCP 67,68 / SNMP 161 |
- Q:UDP 为什么"不粘包"? 它是 datagram 模型,每
recvfrom收到完整一条,边界由协议保留。 - Q:UDP 不可靠,为何 DNS 用它? DNS 多为单请求单响应,UDP 省握手;超时未达应用层重试,简单高效。关键事务可切 TCP(RFC 7766)。
- Q:UDP 没有拥塞控制危险吗? 是。无节制 UDP 会压垮网络,故现代协议(QUIC)在 UDP 之上自建拥塞控制。
- Q:为什么 UDP 最大 65507 字节? 长度字段 16 bit 最大 65535,减 IP(20)+UDP(8)=65507。
- Q:UDP 能广播/组播吗? 能,无连接特性使其天然支持一对多投递。