TCP 头部字段详解
逐字段拆解 TCP 头部的 20 字节,理解每个比特的含义。
1. TCP 头部全景
TCP 头部通常 20 字节(无选项),最大 60 字节。以下是 RFC 9293 定义的标准头部格式:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源端口 (16) | 目的端口 (16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 序列号 (32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 确认号 (32) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|数据偏移| 保留 |C|E|U|A|P|R|S|F| 窗口大小 (16) |
| (4) | (4) |W|C|R|C|S|S|Y|I| |
| | |R|E|G|K|H|T|N|N| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 校验和 (16) | 紧急指针 (16) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项 (可变, 0-40字节) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2. 字段逐一详解
2.1 源端口(Source Port)— 16 位
发送方的端口号。配合源 IP 地址,标识发送方应用程序。
范围:0-65535。0-1023 为知名端口(Well-known Ports,需特权),1024-49151 为注册端口,49152-65535 为动态/私有端口。
2.2 目的端口(Destination Port)— 16 位
接收方的端口号。配合目的 IP 地址,标识接收方应用程序。
常见目的端口举例:
| 端口 | 服务 |
|---|---|
| 80 | HTTP |
| 443 | HTTPS |
| 22 | SSH |
| 3306 | MySQL |
| 6379 | Redis |
2.3 序列号(Sequence Number)— 32 位
核心作用:标识本报文段中第一个数据字节的序列号。
- 范围:0 ~ 2^32-1(约 4.3 GB)
- 当 SYN=1 时,此字段为初始序列号(ISN),第一个数据字节的序列号为 ISN+1
- 序列号循环使用,比较使用模 2^32 运算
RFC 9293: "A fundamental notion in the design is that every octet of data sent over a TCP connection has a sequence number."
2.4 确认号(Acknowledgment Number)— 32 位
仅在 ACK 标志为 1 时有效。表示期望收到的下一个字节的序列号。采用累积确认——确认号 N 意味着 N-1 及之前的所有字节都已成功接收。
连接建立后,ACK 标志必须始终设置(几乎所有 TCP 段都带 ACK)。
2.5 数据偏移(Data Offset)— 4 位
TCP 头部的长度,以 32 位字(4 字节) 为单位。
- 最小值:5(即 5×4 = 20 字节,标准无选项头部)
- 最大值:15(即 15×4 = 60 字节,含最长选项)
- 该字段实际上指向数据从哪里开始
2.6 保留位(Reserved)— 4 位
保留供将来使用。RFC 9293 规定必须设置为 0。历史上这些位未被使用,但未来可能被分配。
2.7 控制位(Control Bits)— 8 位
这是 TCP 头部中最常被考察的部分。RFC 9293 定义了 8 个控制位(相比 RFC 793 原来的 6 个,增加了 CWR 和 ECE):
位: 7 6 5 4 3 2 1 0
+------+------+------+------+------+------+------+------+
| CWR | ECE | URG | ACK | PSH | RST | SYN | FIN |
+------+------+------+------+------+------+------+------+
各控制位作用
| 位 | 名称 | 全称 | 作用 | 何时设置 |
|---|---|---|---|---|
| 7 | CWR | Congestion Window Reduced | 发送方降低了拥塞窗口 | ECN 拥塞响应 |
| 6 | ECE | ECN-Echo | ECN 回显,通知对端网络拥塞 | 收到 CE 标记的 IP 包 |
| 5 | URG | Urgent | 紧急指针字段有效 | 有紧急数据时 |
| 4 | ACK | Acknowledgment | 确认号字段有效 | 几乎所有段(除第一个 SYN) |
| 3 | PSH | Push | 提示接收方尽快将数据交给应用 | 应用层要求立即推送 |
| 2 | RST | Reset | 重置连接 | 异常关闭、拒绝连接 |
| 1 | SYN | Synchronize | 发起连接,同步序列号 | 连接建立(三次握手前两步) |
| 0 | FIN | Finish | 发送方完成数据发送 | 连接关闭 |
重点记忆组合
| 组合 | 含义 |
|---|---|
| SYN=1, ACK=0 | 连接请求(三次握手第一步) |
| SYN=1, ACK=1 | 连接请求确认(三次握手第二步) |
| FIN=1, ACK=1 | 连接释放请求 |
| RST=1 | 连接重置 |
| PSH=1 | 催促接收方尽快上交数据 |
2.8 窗口大小(Window)— 16 位
接收窗口大小。表示发送该段的 TCP 端点还可以接收多少字节(从确认号指示的位置开始)。
- 范围:0 ~ 65535 字节
- 可通过窗口缩放选项(WS) 扩展到最大约 1 GB(2^30 字节)
- 值为 0 表示"暂停发送"
窗口大小是流量控制的核心参数。
2.9 校验和(Checksum)— 16 位
对整个 TCP 段(头部+数据)以及 12 字节的伪头部计算校验和。
伪头部包含:源 IP(4)、目的 IP(4)、协议号(1,TCP=6)、TCP 长度(2)+ 1 字节填充。
校验和采用 16 位反码求和 算法。接收方验证失败则静默丢弃该段。
2.10 紧急指针(Urgent Pointer)— 16 位
仅在 URG=1 时有效。指向紧急数据的最后一个字节的偏移量(相对序列号)。该值 + 序列号 = 紧急数据末尾。
实际应用中紧急指针很少使用。建议使用其他带外信令方式。
3. TCP 选项(Options)
长度可变,最大 40 字节(TCP 头部最长 60 字节,固定部分 20 字节)。选项以 8 位边界结束。
3.1 必选选项(RFC 9293 强制要求)
| Kind | 名称 | 长度 | 说明 |
|---|---|---|---|
| 0 | EOL (End of Option List) | 1 | 标记选项列表结束 |
| 1 | NOP (No-Operation) | 1 | 无操作,用于对齐填充 |
| 2 | MSS (Maximum Segment Size) | 4 | 最大段大小协商 |
3.2 常用可选选项
| Kind | 名称 | RFC | 说明 |
|---|---|---|---|
| 3 | WS (Window Scale) | 7323 | 窗口缩放,左移 0-14 位 |
| 4 | SACK-Permitted | 2018 | 声明支持选择性确认 |
| 5 | SACK | 2018 | 选择性确认的具体块信息 |
| 8 | TS (Timestamp) | 7323 | 时间戳,用于 RTT 测量和 PAWS |
4. Wireshark 中的 TCP 头部
在 Wireshark 中抓包可以看到典型的 TCP 头部:
Transmission Control Protocol, Src Port: 54321, Dst Port: 443, Seq: 1, Ack: 1, Len: 0
Source Port: 54321
Destination Port: 443
[Stream index: 5]
[Conversation completeness: Complete, WITH_DATA (31)]
Sequence Number: 1 (relative sequence number)
Acknowledgment Number: 1 (relative ack number)
1000 .... = Header Length: 32 bytes (8)
Flags: 0x018 (PSH, ACK)
Window: 65535
Checksum: 0x1234 [unverified]
Urgent Pointer: 0
Options: (12 bytes), No-Operation (NOP), No-Operation (NOP), Timestamps
Wireshark 默认显示相对序列号(方便阅读),可以用右键切换为绝对序列号。
本篇要点
- TCP 头部固定 20 字节,最大 60 字节(数据偏移字段 4 位,最大值 15×4=60)
- 序列号标识段中第一个数据字节的编号;确认号表示期望收到的下一个字节编号(累积确认)
- 8 个控制位:CWR、ECE(ECN 拥塞相关)、URG(紧急)、ACK(确认号有效)、PSH(推送)、RST(重置)、SYN(同步)、FIN(结束)
- 窗口大小 16 位(最大 64KB),通过窗口缩放选项可扩展到约 1GB
- 校验和覆盖范围:伪头部 + TCP 头部 + TCP 数据
- MSS 选项仅在 SYN 段中发送,以太网环境下通常为 1460 字节
- SYN 和 FIN 各消耗一个序列号,纯 ACK 不消耗序列号