Appearance
TCP 协议
TCP(Transmission Control Protocol,传输控制协议)是 TCP/IP 协议族中传输层的两个核心协议之一,与 UDP 并列。它在 IP 协议(网络层)之上提供面向连接、可靠、字节流的传输服务,是Web、邮件、文件传输等绝大多数应用的底座。
一句话:UDP 提供传输能力,TCP 提供传输保证。 TCP 通过一整套机制把「不可靠的 IP 网络」包装成「对应用层可靠的字节流」。
一、TCP 的核心特征
- 面向连接:通信前必须「三次握手」建立连接,结束后「四次挥手」释放。
- 可靠交付:通过序号、确认(ACK)、超时重传、校验和保证数据不丢、不重、按序到达。
- 字节流:没有消息边界,发送方多次写、接收方可能一次读(或反之)——存在「粘包/拆包」,需要应用层自己定界。
- 流量控制:通过滑动窗口让发送方不超过接收方的处理能力。
- 拥塞控制:通过慢启动、拥塞避免、快重传、快恢复等算法,在网络拥塞时主动减速,避免雪崩。
- 全双工:连接建立后,双方可同时收发。
二、TCP 报文格式
0 1 2 3
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 源端口 | 目的端口 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 序号 seq |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 确认号 ack |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据偏移 | 保留 |U|A|P|R|S|F| 窗口大小 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 校验和 | 紧急指针 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 选项(可选,如 MSS、窗口扩大) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 数据 ... |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+| 字段 | 说明 |
|---|---|
| 源/目的端口 | 标识两端进程,各 16 位 |
| 序号 seq | 本报文段首个字节在数据流中的位置 |
| 确认号 ack | 期望收到的下一个字节的序号(累计确认) |
| 数据偏移 | 首部长度(以 4 字节为单位,含选项) |
| 标志位 | URG/ACK/PSH/RST/SYN/FIN,控制连接状态 |
| 窗口 | 接收方当前可接收的字节数(流量控制) |
| 校验和 | 覆盖首部+数据+伪首部 |
| 紧急指针 | URG=1 时有效,指出紧急数据末尾 |
常用标志位:
- SYN:同步序号,用于建立连接(三次握手)。
- ACK:确认有效。
- FIN:释放连接(四次挥手)。
- RST:复位,异常中断连接。
- PSH / URG:尽快交付 / 紧急数据。
三、三次握手(建立连接)
客户端 服务端
| |
| ---- SYN, seq=x ------------------> | ① 服务端进入 LISTEN
| |
| <--- SYN+ACK, seq=y, ack=x+1 ----- | ② 服务端进入 SYN_RCVD
| |
| ---- ACK, seq=x+1, ack=y+1 -------> | ③ 双方进入 ESTABLISHED
| |目的:双方确认彼此的收发能力都正常,并同步初始序号。防止已失效的连接请求突然又传到服务端造成误建。
四、四次挥手(释放连接)
客户端 服务端
| |
| ---- FIN, seq=u ------------------> | ① 客户端 FIN_WAIT_1
| <--- ACK, ack=u+1 ---------------- | ② 服务端 CLOSE_WAIT(仍可发数据)
| |
| <--- FIN, seq=v ------------------- | ③ 服务端发完数据后 LAST_ACK
| ---- ACK, ack=v+1 ---------------> | ④ 客户端 TIME_WAIT → 2MSL 后 CLOSE为什么挥手是四次而不是三次? 因为 TCP 全双工,关闭时每个方向都要单独关闭:被动方收到 FIN 后先回 ACK(确认收到),但可能还有数据要发,等自己也没数据了再发 FIN。所以 ACK 和 FIN 被拆成了两个报文。
TIME_WAIT 与 2MSL:主动关闭方最后会进入 TIME_WAIT 并等待 2MSL(最长报文段寿命),确保最后的 ACK 能到达、且旧连接的残留报文在网络中消失,避免影响新连接。
五、可靠性机制
- 序号 + 确认:接收方用 ack 告知「已正确收到到哪」,发送方据此判断哪些需要重传。
- 超时重传(RTO):报文超时未收到 ACK 即重发;RTO 随网络状况动态估算。
- 滑动窗口:接收方通过
窗口字段告诉发送方「我还能收多少」,实现流量控制。 - 拥塞控制:
慢启动 → 拥塞避免 → 快重传/快恢复,根据丢包/延迟推测网络容量,避免把网络打满。
六、与 UDP 对比
| 特性 | TCP | UDP |
|---|---|---|
| 连接性 | 面向连接(三次握手、四次挥手) | 无连接 |
| 可靠性 | 可靠(确认、重传、序号) | 不可靠(尽最大努力交付) |
| 顺序性 | 保证按序到达 | 不保证顺序 |
| 数据边界 | 字节流,无消息边界(可能粘包/拆包) | 保留报文边界(面向报文) |
| 速度 | 较慢(握手、确认、控制开销) | 较快 |
| 首部开销 | 20~60 字节 | 8 字节 |
| 流量/拥塞控制 | 有 | 无 |
| 通信模式 | 仅一对一 | 一对一、一对多、广播/组播 |
| 适用场景 | 文件传输、网页、邮件、SSH | 音视频、DNS、游戏、实时通信 |
七、典型应用
- HTTP / HTTPS:网页传输(HTTP/3 例外,底层是 QUIC over UDP)。
- FTP / SMTP / POP3:文件传输、邮件。
- SSH / Telnet:远程登录。
- 数据库连接、消息队列等长连接、强可靠场景。
八、常见问题
Q1:TCP 会粘包吗?怎么解决? 会。TCP 是字节流,不存在消息边界,发送端多次 write 可能被合并、一次 read 可能拿到多段。解决办法(应用层定界):固定长度、长度前缀、分隔符、或每次一发一收(短连接/请求-响应模型)。
Q2:为什么 TIME_WAIT 要等 2MSL? 确保最后的 ACK 能到达被动方;同时让本连接产生的所有报文在网络中消亡,避免被后续同源同端口的新连接误收。
Q3:TCP 和 UDP 怎么选? 对可靠性、顺序敏感(文件、网页、交易)→ TCP;对延迟敏感、可容忍丢包、需要广播/组播(音视频、游戏、DNS)→ UDP;也可像 QUIC 那样在 UDP 上自建可靠。