TCP 三次握手与四次挥手
为什么要"握手"
TCP 是可靠传输协议,通信前双方必须确认:我能发、你能收;你能发、我能收。三次握手就是用最少次数完成这个双向确认。
三次握手(建立连接)
用打电话来类比:
第一次:A → B:"喂,你能听到我吗?"(SYN)
第二次:B → A:"能听到,你能听到我吗?"(SYN + ACK)
第三次:A → B:"能听到,开始说吧。"(ACK)技术细节:
| 步骤 | 方向 | 标志位 | 作用 |
|---|---|---|---|
| 第一次 | Client → Server | SYN=1, seq=x | 客户端发起连接请求 |
| 第二次 | Server → Client | SYN=1, ACK=1, seq=y, ack=x+1 | 服务端确认并同步 |
| 第三次 | Client → Server | ACK=1, seq=x+1, ack=y+1 | 客户端确认,连接建立 |
为什么是三次不是两次? 防止已失效的连接请求突然到达服务端,导致服务端白白开启连接浪费资源。
四次挥手(断开连接)
TCP 是全双工的,两个方向要分别关闭:
第一次:A → B:"我说完了。"(FIN)
第二次:B → A:"知道了,我还没说完。"(ACK)
第三次:B → A:"我也说完了。"(FIN)
第四次:A → B:"好的,挂了。"(ACK)为什么是四次不是三次? 因为服务端收到 FIN 时可能还有数据没发完,所以 ACK 和 FIN 不能合并(不像握手时 SYN+ACK 可以合并)。
TIME_WAIT 状态
主动关闭的一方在发送最后一个 ACK 后,会进入 TIME_WAIT 状态,等待 2MSL(通常 60 秒)才真正关闭。
原因:确保最后一个 ACK 能到达对方。如果对方没收到 ACK 会重发 FIN,此时本方还能重新 ACK。
面试高频追问
Q: 大量 TIME_WAIT 怎么办? A: 开启 tcp_tw_reuse,或使用连接池复用连接。
Q: 大量 CLOSE_WAIT 说明什么? A: 说明本方应用没有正确调用 close(),是代码 bug,不是网络问题。
Q: 为什么不用两次握手? A: 无法防止历史重复连接(网络延迟导致旧 SYN 迟到)。