1. UDP 协议基础回顾:报文结构、与 TCP 核心区别、不可靠性本质
各位好,我是老赵。做网络排查这么多年,我见过太多人一遇到 UDP 丢包就慌了神。其实,要解决丢包问题,得先搞清楚 UDP 到底是个什么脾气。这一章,咱们就从头捋一捋 UDP 的基础。
1.1 UDP 报文结构:轻量到极致
UDP 的报文头,简单得让人心疼。它只有 8 个字节。你想想看,TCP 光头部就至少 20 字节,UDP 这 8 个字节能干吗?
| 字段 | 长度(位) | 说明 |
|---|---|---|
| 源端口 | 16 | 发送方端口号,可选(可为 0) |
| 目的端口 | 16 | 接收方端口号,必填 |
| 长度 | 16 | UDP 头部 + 数据的总长度(字节) |
| 校验和 | 16 | 覆盖头部和数据,可选(IPv4 下可为 0) |
说白了,UDP 就是「我发我的,你收你的」。它不关心对方在不在,也不关心数据到没到。我在项目中遇到过有人把校验和关了,结果数据在传输过程中被静默篡改,排查了整整两天才发现。嗯,这里要注意:虽然校验和可选,但我建议永远不要关掉它。
核心要点:UDP 头部只有 8 字节,没有序号、确认号、窗口、标志位等 TCP 的复杂字段。这就是它「快」的根本原因,也是它「不可靠」的根源。
1.2 UDP 与 TCP 核心区别:一个像快递,一个像挂号信
我经常跟团队里的新人打比方:TCP 是挂号信,UDP 是普通快递。挂号信要签收、要回执、丢了还能追查;普通快递扔门口就走,丢了只能认栽。
具体区别,我整理了一张表,你一看就明白:
| 对比维度 | UDP | TCP |
|---|---|---|
| 连接状态 | 无连接 | 面向连接(三次握手) |
| 可靠性 | 尽最大努力交付,不保证 | 保证可靠传输(重传、确认) |
| 有序性 | 不保证顺序 | 保证字节流顺序 |
| 流量控制 | 无 | 有(滑动窗口) |
| 拥塞控制 | 无 | 有(慢启动、拥塞避免) |
| 头部开销 | 8 字节 | 20-60 字节 |
| 传输模式 | 报文边界保留 | 字节流,无边界 |
为什么 UDP 没有拥塞控制?因为它压根不关心网络堵不堵。我曾经在一个视频直播项目中,因为 TCP 的拥塞控制导致画面卡顿,换成 UDP 后延迟直接降到 50ms 以内。当然,代价就是偶尔会花屏——这就是不可靠性的代价。
避坑指南:我曾经见过有人用 UDP 传数据库日志,结果丢了几条关键记录,导致数据不一致。记住:需要可靠传输的场景,别用 UDP 裸奔。
1.3 UDP 的不可靠性本质:为什么它「不负责」?
UDP 的不可靠性,说白了就是三个字:不确认。
发送方把数据包扔到网络上,就不管了。它不会问接收方「收到了吗?」,接收方也不会主动说「收到了」。如果中间路由器丢包了,或者接收方缓冲区满了,数据就悄无声息地消失了。
为什么会这样?因为 UDP 的设计哲学是「快」。它把可靠性这个包袱甩给了上层应用。你想想看,如果每个包都要确认、都要重传,那延迟肯定上去了。对于实时语音、视频、游戏来说,丢几个包可以忍,但延迟高了就完全没法用。
我画了一张图,帮你理解 UDP 的「无状态」本质:
从图上你能看到,UDP 的通信模型就是一条单行道。发送方把数据丢进网络,接收方能不能收到,全看网络心情。没有握手、没有挥手、没有确认、没有重传。
警告:UDP 的校验和虽然是可选的,但在 IPv6 下是强制的。如果你在 IPv6 环境中关闭了校验和,数据包会被直接丢弃。我曾经踩过这个坑,切记!
1.4 小结:理解不可靠,才能驾驭不可靠
UDP 的不可靠性,不是设计缺陷,而是设计取舍。它把可靠性交给了上层应用,换来了极低的延迟和极小的开销。对于实时通信、DNS 查询、DHCP、视频流等场景,UDP 是无可替代的选择。