2. UDP 报文格式:拆开来看,其实很简单
上一章我们聊了 UDP 的“快”和“不靠谱”,那它到底长什么样?
说白了,UDP 报文就是一段二进制数据,前面加了个 8 字节的头部。这个头部非常精简,只有四个字段。我刚开始学网络编程时,看到 TCP 那动辄 20 字节的头部就头疼,UDP 这个清爽多了。
2.1 UDP 报文整体结构
UDP 报文由两部分组成:UDP 头部 和 UDP 数据。头部固定 8 字节,数据部分最长可以到 65527 字节(理论值)。
先看一张整体结构图,心里有个谱:
嗯,结构就这么简单。下面我们逐个字段拆开讲。
2.2 源端口(Source Port)—— 2 字节
源端口标识发送方的进程。你想想看,一台机器上可能同时跑着好几个网络应用——浏览器、游戏、视频通话……操作系统怎么区分哪个数据包是发给谁的?靠的就是端口号。
- 范围:0 ~ 65535
- 作用:告诉接收方,“回信请寄到这个端口”
- 注意:如果发送方不需要回复(比如单向日志上报),源端口可以填 0
2.3 目的端口(Destination Port)—— 2 字节
目的端口标识接收方的进程。这个字段必须填,不能为 0。
举个例子:你电脑上的 QQ 想给朋友的发消息。QQ 会把自己的端口填在源端口,把的端口填在目的端口。网络上的路由器只看 IP 地址把包送到朋友电脑,到了朋友电脑上,操作系统再看目的端口,把数据交给。
| 端口范围 | 分类 | 常见例子 |
|---|---|---|
| 0 - 1023 | 知名端口(Well-Known Ports) | DNS 使用 53,DHCP 使用 67/68 |
| 1024 - 49151 | 注册端口(Registered Ports) | 很多游戏服务器用 27015 |
| 49152 - 65535 | 动态/私有端口(Dynamic/Private Ports) | 客户端临时分配,用完就释放 |
2.4 长度(Length)—— 2 字节
这个字段表示整个 UDP 报文的长度,单位是字节。包括头部 8 字节 + 数据部分。
- 最小值:8(只有头部,没有数据)
- 最大值:65535(理论值,实际受限于 IP 层)
你可能会问:“既然 IP 层已经知道总长度了,为什么 UDP 还要再算一遍?”
嗯,这是个好问题。其实这是为了冗余校验。IP 层可能会对数据包做分片重组,UDP 层拿到的不一定是完整的原始包。长度字段让接收方可以验证:“我收到的数据长度对不对?”如果对不上,直接丢弃。
核心要点:长度字段 = UDP 头部(8 字节)+ UDP 数据长度。计算数据部分长度时,记得减去 8。
2.5 校验和(Checksum)—— 2 字节
校验和是 UDP 唯一的差错检测机制。它覆盖了 UDP 头部、数据部分,以及一个伪头部。
什么是伪头部?它并不是 UDP 报文的一部分,而是从 IP 头部里“借”来的信息——源 IP 地址、目的 IP 地址、协议类型、UDP 长度。为什么要包含这些?
说白了,就是为了防止数据包被送错地方。比如,一个包本来要发给 192.168.1.10,结果网络出了问题,送到了 192.168.1.11。如果校验和不包含 IP 地址,接收方检查 UDP 校验和会发现数据没损坏,就收下了——这就出大问题了。伪头部让接收方可以确认:“这个包确实是给我的。”
校验和的计算过程:
- 发送方把校验和字段置为 0
- 将伪头部、UDP 头部、数据部分按 16 位一组进行二进制反码求和
- 将结果取反,填入校验和字段
- 接收方收到后,同样计算一遍,如果结果为 0,说明数据完整
2.6 伪头部(Pseudo Header)—— 不在报文里,但很重要
伪头部是计算校验和时临时构造的 12 字节结构,不参与网络传输。它的组成如下:
| 字段 | 长度 | 说明 |
|---|---|---|
| 源 IP 地址 | 4 字节 | 来自 IP 头部 |
| 目的 IP 地址 | 4 字节 | 来自 IP 头部 |
| 保留位 | 1 字节 | 固定为 0 |
| 协议类型 | 1 字节 | UDP 固定为 17(0x11) |
| UDP 长度 | 2 字节 | 与 UDP 头部的长度字段一致 |
你看,伪头部把 IP 层的地址信息“绑定”到了 UDP 校验和里。这样即使 IP 层出了错,UDP 也能发现。
2.7 各字段作用总结
最后,我用一个表格把四个字段的作用串起来,方便你复习:
| 字段 | 大小 | 作用 | 必须填? |
|---|---|---|---|
| 源端口 | 2 字节 | 标识发送方进程,用于回信 | 可选(可填 0) |
| 目的端口 | 2 字节 | 标识接收方进程,数据分发依据 | 必须 |
| 长度 | 2 字节 | 整个 UDP 报文长度(头部+数据) | 必须 |
| 校验和 | 2 字节 | 检测数据在传输中是否损坏或送错 | IPv4 可选,IPv6 必须 |