一、TCP 协议概述
TCP(Transmission Control Protocol,传输控制协议)是 TCP/IP 协议栈中传输层的核心协议。 它提供面向连接的、可靠的、基于字节流的传输服务。 与 UDP 的"尽最大努力交付"不同,TCP 通过序列号、确认应答、重传机制、流量控制和拥塞控制来保证数据可靠到达。
TCP 像打电话 — 先拨号建立连接,确认对方在听,然后逐句交流,说完挂断。UDP 像寄明信片 — 写完直接扔进邮筒,不关心对方是否收到。
二、TCP 报文头部结构
TCP 报文头部固定为 20 字节(不含选项),下图逐字段展示其结构:
关键字段说明
| 字段 | 大小 | 说明 |
|---|---|---|
| 源端口 | 16 bit | 发送方端口号,标识发送数据的应用 |
| 目的端口 | 16 bit | 接收方端口号,标识接收数据的应用 |
| 序列号 (seq) | 32 bit | 本报文数据部分第一个字节的编号,保证数据有序到达 |
| 确认号 (ack) | 32 bit | 期望收到的下一个字节的序号,即"ack 之前的所有数据已收到" |
| 数据偏移 | 4 bit | TCP 头部长度(以 4 字节为单位),实际头部长度 = 此值 × 4 |
| 窗口大小 (Window) | 16 bit | 接收方告知发送方自己还能接收多少数据,用于流量控制 |
| 校验和 (Checksum) | 16 bit | 覆盖 TCP 头部、数据和伪首部,用于差错检测 |
| 紧急指针 | 16 bit | 当 URG=1 时有效,指出紧急数据末尾在报文中的位置 |
六个标志位(Flags)
| 标志 | 全称 | 含义 |
|---|---|---|
| URG | Urgent | 紧急指针有效,报文含高优先级数据 |
| ACK | Acknowledgment | 确认号有效,除初始 SYN 外几乎所有报文都置 1 |
| PSH | Push | 要求接收方立即将数据交给应用层,不等缓冲区满 |
| RST | Reset | 重置连接,用于异常情况下的连接中断 |
| SYN | Synchronize | 同步序列号,用于建立连接 |
| FIN | Finish | 发送方数据已完毕,请求关闭连接 |
三、三次握手 — 建立连接
TCP 建立连接需要三次交互(Three-Way Handshake),确保双方都准备好通信并同步序列号:
为什么是三次而不是两次?
如果只有两次握手(Client 发 SYN,Server 回 SYN+ACK 后直接建立连接),存在一个经典问题: 假设 Client 发出的第一个 SYN 因网络延迟迟迟未到达,Client 超时后重发了一个新的 SYN 并成功建立连接、完成数据传输、关闭连接。 之后那个迟到的旧 SYN 到达 Server,Server 回复 SYN+ACK 并建立连接 — 但这个连接 Client 根本不需要,Server 的资源被白白浪费。
三次握手解决了这个问题:Client 收到 Server 的 SYN+ACK 后,还要再发一个 ACK 确认。如果 Client 没有发起连接请求,它不会发 ACK,Server 收不到 ACK 就不会真正建立连接,超时后自动释放。
四、四次挥手 — 关闭连接
TCP 是全双工通信,关闭连接需要双方各自独立关闭自己的发送通道,因此需要四次交互:
MSL(Maximum Segment Lifetime)是报文最大生存时间。Client 发出最后一个 ACK 后等待 2MSL 有两个目的: 1. 确保最后一个 ACK 能到达 Server。如果 Server 没收到,会重发 FIN,Client 在 TIME_WAIT 期间还能收到并重新发送 ACK。 2. 等待本连接的所有残留报文在网络中消亡,防止干扰新连接(如果新连接复用了相同的端口和序列号)。
五、TCP 可靠性机制总结
| 机制 | 解决的问题 | 实现方式 |
|---|---|---|
| 序列号 + 确认号 | 数据乱序、重复 | 每个字节编号,按序组装 |
| 超时重传 | 数据丢失 | 发送后启动定时器,超时未收到 ACK 则重传 |
| 滑动窗口 | 流量控制 | 接收方通过 Window 字段通告可用缓冲区大小 |
| 拥塞控制 | 网络拥塞 | 慢启动、拥塞避免、快重传、快恢复 |
| 校验和 | 数据损坏 | 对头部和数据计算校验和,接收方验证 |
TCP 的复杂性全部服务于一个目标:在不可靠的 IP 网络之上提供可靠的数据传输。理解 TCP 头部结构和状态机转换,是分析网络问题(如连接超时、丢包、重传)的基础。Wireshark 抓包时,每一个字段都能在这张结构图中找到对应位置。