本文对 TCP 的三次握手和四次挥手做一个通俗的解释,不会介绍细节,只会进行场景化的描述,让人容易理解。
我们把 TCP 连接类比成老 A 给老 B 打一个电话。
三次握手
- 一次握手 (老 A → 老 B,SYN 包):老 A 喊:"老 B,是你不?我是老 A,找你说点事。"(对应:客户端发 SYN 包,告知服务端 "我要建立连接,我的初始序列号是 X",仅发起呼叫,未确认任何能力。)
- 二次握手 (老 B → 老 A,SYN+ACK 包):老 B 回应:"老 A 我听到了,是我!你说,我听着。"(对应:服务端发 SYN+ACK 包,两层确认:① 收到你的呼叫(ACK = X+1);② 我也准备好连接了(我的初始序列号是 Y)。此时老 A 能确认 "自己能发、老 B 能收 + 老 B 能发"。)
- 三次握手 (老 A → 老 B,ACK 包):老 A 接话:"好嘞,我这就说。"(对应:客户端发 ACK 包,确认 "收到你的准备信号(ACK = Y+1)"。老 B 收到后确认 "自己能发、老 A 能收",双方均进入连接状态,可开始传数据。)
注 :三次握手阶段若出现包丢失(SYN / SYN+ACK 丢失),核心靠「报文重传 + 超时兜底」处理:丢失的一方会触发重传计时器,多次重传失败后直接超时断链。
四次挥手
老 A 和老 B 正常聊天(TCP 已建立 ESTABLISHED 连接,双向传输数据),老 A 先发起关闭(对应 TCP 主动关闭方,老 B 为被动关闭方)。
- 第一次挥手 (老 A → 老 B,FIN 包):老 A:"我说完了,没别的要讲了,你那边还有要跟我说的吗?"✅ 对应 TCP:主动关闭方(老 A)发 FIN 包,请求关闭自己到对方的通信链路(老 A → 老 B 的发送端关闭),老 A 进入 FIN-WAIT-1 状态,等待老 B 确认。
- 第二次挥手 (老 B → 老 A,ACK 包):老 B:"好的,我收到你说的了,你那边我就不听了!我这边还有点收尾的话要捋一捋,你等我说完哈。"✅ 对应 TCP:被动关闭方(老 B)先回 ACK 包,确认收到 FIN 包(老 B 知道老 A 不发了),老 B 进入 CLOSE-WAIT 状态(半关闭状态:老 A → 老 B 的链路关了,但老 B → 老 A 的链路还能发,老 B 可以继续传剩余数据);老 A 收到 ACK 后进入 FIN-WAIT-2 状态,等待老 B 的最终关闭通知。
- 第三次挥手 (老 B → 老 A,FIN 包):老 B:"我这边也捋完了,没别的要说的了,我也说完了!"✅ 对应 TCP:老 B 把自己的剩余数据发完后,发 FIN 包,请求关闭自己到老 A 的通信链路(老 B → 老 A 的发送端关闭),老 B 进入 LAST-ACK 状态,等待老 A 的最终确认。
- 第四次挥手 (老 A → 老 B,ACK 包):老 A:"好的,收到你也说完了,那咱彻底结束,再见!"✅ 对应 TCP:老 A 回 ACK 包,确认收到老 B 的 FIN 包,老 A 进入 TIME-WAIT 状态(等待 2MSL,防止滞留报文),老 B 收到 ACK 后直接关闭连接(CLOSED);老 A 等待超时后,也彻底关闭连接。
注 :这是正常场景。异常场景下,TCP 断链的主要办法是超时。