Skip to content

概念卡片:TCP 三次握手与四次挥手

一句话机制:TCP 靠三次握手建立连接(双方确认自己与对方的收、发都正常),靠四次挥手释放连接(因为 TCP 是「半关闭」,一方发 FIN 只表示自己不再发数据,对方可能还要发,所以 ACK 与 FIN 必须分开)。握手的本质是交换并确认双方的序列号起始值(seq)

三次握手时序

方向标志位序列号/确认号状态
1C → SSYN=1seq=xC 进 SYN_SENT
2S → CSYN=1, ACK=1seq=y, ack=x+1S 进 SYN_RCVD
3C → SACK=1seq=x+1, ack=y+1双方进 ESTABLISHED

每一轮「谁确认了什么」:

  • 第一次:Client 什么都不能确认;Server 确认「对方发送正常、自己接收正常」。
  • 第二次:Client 确认「自己收发正常、对方收发正常」;Server 仍只确认「对方发送正常、自己接收正常」。
  • 第三次:双方都确认「自己收发正常、对方收发正常」。缺一不可。

为什么要三次,两次不行吗?

TCP 可靠传输的关键是维护序列号。三次握手 = 双方互相告知序列号起始值 + 确认对方已收到。若只有两次握手,至多只有客户端的起始序列号能被确认,服务器的序列号得不到确认,无法双向可靠。

四次挥手时序

方向标志位说明
1C → SFIN=1C 关闭到 S 的数据传送,进 FIN-WAIT-1
2S → CACK=1S 确认收到(ack=seq+1),进 CLOSE-WAIT;C 进 FIN-WAIT-2
3S → CFIN=1S 发完最后数据后发 FIN,进 LAST-ACK
4C → SACK=1C 确认,进 TIME-WAIT(2MSL 后才 CLOSED);S 收到后立即 CLOSED

FIN 报文即使不携带数据也要消耗一个序号;服务端结束连接比客户端早(客户端要等 2*MSL)。

为什么挥手要四次,三次不行吗?

FIN 只表示「对方没数据发给你了」,未必你也没数据发给对方。所以收到 FIN 的一方先回 ACK(表示收到),等自己数据发完再发 FIN。握手时 ACK 和 SYN 能一起发(SYN 请求可立即应答),挥手时 ACK 和 FIN 大概率分开发——故四次。

关键代码/报文示例

三次握手标志位变化:

C --SYN(seq=x)--> S
C <--SYN+ACK(seq=y,ack=x+1)-- S
C --ACK(seq=x+1,ack=y+1)--> S

不变量(必须成立的约束)

  • 握手确认「收发都正常」;挥手 ACK 与 FIN 分开发。
  • SYN、FIN 都占用一个序号。
  • 客户端 TIME-WAIT 要等 2*MSL(最长报文段寿命)才 CLOSED,用于保证最后一个 ACK 能到达、让旧连接报文在网络中消失。

常见误解

  • 以为「两次握手就够」→ 服务器序列号无法被确认,不能建立双向可靠传输。
  • 以为「挥手三次就够」→ 忽略 TCP 半关闭,ACK 和 FIN 因可能还有数据要发而必须分开。
  • 以为「TIME-WAIT 是服务端状态」→ 是主动关闭方(客户端)的状态。

关联

最近更新