适用网页直接发布,段落清晰、无复杂markdown语法,通俗易懂,附带和UDP对比、ACK原理,承接我们前面讨论的带宽、确认包知识点
很多开发、运维同学天天和TCP打交道,知道TCP可靠、有ACK确认、会重传;UDP包头小、无回执,实时场景更省带宽。但绝大多数人只停留在概念层面:TCP数据包在网线里真实的二进制结构到底长什么样?三次握手、ACK确认、流量控制,全部功能都写在TCP头部几十个字节中。
本文逐层拆解标准TCP报文结构,结合抓包现象,带你直观看懂TCP数据包。
一、数据包分层封装:先理清位置
当程序发送一段数据,操作系统会层层封装报文,以太网环境完整封装顺序:
[以太网头部] [IP头部] [TCP头部] [应用层载荷数据]
我们今天聚焦 TCP头部 。
注意区分两个容易混淆概念:
- TCP报文段(Segment):传输层单元,包含TCP头+业务数据
- IP数据包(Packet):网络层单元,IP头 + TCP整个报文段
TCP头部有一个关键特性:最小20字节,最大60字节 。多出的空间用于TCP可选扩展字段(时间戳、SACK、窗口缩放等)。
对比记忆:UDP头部固定只有8字节,这也是同等条件下UDP头部开销更小的根源。
二、TCP头部标准结构图(32bit为一行)
标准TCP头部布局(单位:比特bit,8bit=1字节)
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
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源端口(16bit) | 目标端口(16bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 序列号(32bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 确认号ACK(32bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据偏移 |保留|标志位| 接收窗口大小(16bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 校验和(16bit) | 紧急指针(16bit) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 可选字段(0~40字节) + 填充 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 应用载荷数据 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
三、逐个字段通俗讲解
1. 源端口(16bit) / 目标端口(16bit)
端口标识,区分同一台主机上不同应用程序。
例如:客户端随机端口 → 服务器80/443端口。
UDP头部同样存在这两个字段。
2. 序列号 Sequence Number(32bit)
TCP把所有传输数据当成一串连续字节流。
序列号代表:当前报文携带数据的第一个字节编号。
作用:解决乱序、重复报文问题,保障有序交付。
3. 确认号 Acknowledgment Number(32bit)【重点!ACK包核心】
也就是我们上一轮聊的ACK确认机制核心字段。
规则:确认号 = N,代表接收方已经成功收到 N 之前所有字节,期待下一次接收字节N。
举例子:接收方收到1~1000字节,回复确认号1001。
这就是ACK回执包的本质。
⚠️ 重要前提:TCP头部的ACK标志位必须开启,这个确认号才生效。
4. 数据偏移(4bit)
单位:4字节。用来标识TCP头部总长度。
最小值5(5×4=20字节),对应无选项的基础头部;最大值15(60字节)。
这直接印证:TCP头部20~60字节可变。
5. 6个核心标志位(Flags),抓包最常看见
一共6个1bit标记,可以同时多个置1:
- URG:紧急指针有效
- ACK:确认位。只要置1,确认号字段生效。绝大多数TCP包都开启ACK
- PSH:推送,通知内核立刻把数据交给应用程序,不要缓冲区排队
- RST:重置连接,强制断开
- SYN:同步,三次握手建立连接
- FIN:结束,四次挥手关闭连接
Wireshark抓包里看到 [SYN] [ACK] [PSH,ACK] 来源就是这一组标志。
6. 接收窗口 Window(16bit)
流量控制核心。告诉发送方:我接收缓冲区还有多少空闲空间,你别发太快。
配合拥塞控制,防止发送方打爆接收端。
7. 校验和 Checksum(16bit)
校验TCP头部+数据,检测传输过程是否出现比特损坏。UDP也有校验和。
8. 紧急指针 Urgent Pointer(16bit)
URG标志生效时使用,标记紧急数据位置,日常业务极少用到。
9. 可选字段 Options(0 ~ 40字节)
常用选项:
- MSS:最大报文段长度
- Window Scale:窗口缩放,解决大带宽高速传输
- Timestamps:时间戳,用于RTT计算、防序列号回绕
- SACK:选择性确认,丢包时不用全部重传,优化性能
只要启用任意选项,TCP头部就会大于基础20字节,进一步增加带宽开销。
四、结合带宽话题:TCP为什么比UDP更耗流量?
-
头部尺寸差距
UDP固定8字节头部;TCP最少20字节,开启选项后通常32~40字节。小包场景(游戏、传感器上报)头部占比极高,差距明显。
-
大量额外ACK报文
单向数据流场景下,接收方持续发送纯ACK小包。
只有TCP原生携带ACK机制;UDP协议层不存在任何确认回执。
直播推流场景:TCP上行推视频数据,下行源源不断ACK回执,双向产生流量;UDP只有上行数据流。
- 重传报文开销
网络丢包时,发送方收不到ACK,触发重传,重复发送相同数据。
补充提醒:
如果在UDP之上自研可靠传输(KCP、QUIC),应用层自己实现ACK、重传。此时UDP协议头虽然很小,但上层自定义控制包会补齐开销,带宽优势大幅缩水。
五、实战小提示:Wireshark抓包观察TCP包
- 过滤表达式:
tcp - 点开任意报文,展开
Transmission Control Protocol - 可以清晰看到:Source Port、Seq、Ack、Flags、Window、Options
- 纯ACK包特征:TCP载荷长度=0,仅有ACK标记,无业务数据,这类就是我们所说的ACK确认包。
六、总结
- TCP头部:20~60字节可变;UDP固定8字节,基础开销UDP更小。
- 序列号、ACK确认号、标志位、窗口大小,共同实现TCP三大特性:有序传输、可靠送达、流量控制。
- ACK确认号是TCP可靠传输的基石,也是TCP额外消耗带宽的关键原因。
- 所有TCP复杂功能,没有魔法,全部定义在这几十字节的头部二进制字段中。