八股文解析
TCP 三次握手与 TIME_WAIT 详解
TCP 三次握手与 TIME_WAIT 详解
一句话结论
- 三次握手:确认双方收发能力正常,同步初始序列号
- TIME_WAIT:主动关闭方等待 2MSL,确保最后一个 ACK 到达对方,并让旧报文自然消亡
面试标准答法
三次握手
客户端 服务端
|------- SYN seq=x -------->|
|<---- SYN+ACK seq=y, ack=x+1 --|
|------- ACK ack=y+1 ------->|为什么不能两次?
- 防止已失效的连接请求突然传到服务端,造成资源浪费
- 双方都要确认对方的收发能力正常
四次挥手
主动方 被动方
|------- FIN seq=u -------->|
|<------ ACK ack=u+1 -------|
|<------ FIN seq=v ---------|
|------- ACK ack=v+1 ------->|为什么挥手要四次?
- 被动方收到 FIN 后,可能还有数据没发完,先回 ACK,发完后再发 FIN
TIME_WAIT
- 出现在主动关闭方
- 时长:2MSL(Maximum Segment Lifetime,Linux 默认 60s,即 120s)
两个作用:
- 确保最后一个 ACK 能到达被动方;若丢失,被动方会重发 FIN
- 让本连接产生的所有报文都从网络中消失,避免影响下一个相同四元组的连接
线上问题与调优
| 问题 | 原因 | 处理 |
|---|---|---|
| 大量 TIME_WAIT | 高并发短连接,主动关闭多 | 开 tcp_tw_reuse;用长连接/连接池;调大 tcp_max_tw_buckets |
| SYN Flood | 半连接队列被打满 | 开 tcp_syncookies;调大 tcp_max_syn_backlog;防火墙限流 |
常见追问
| 追问 | 要点 |
|---|---|
| 为什么不是两次握手? | 无法阻止历史重复连接初始化 |
| 为什么不是三次挥手? | 被动方可能还有数据要发 |
| TIME_WAIT 在客户端还是服务端? | 看谁主动发第一个 FIN |
| HTTP 如何减少 TIME_WAIT? | Keep-Alive 长连接复用 |
面试回答模板(30 秒版)
延伸准备
- 能画出 TCP 状态转换图
- 能解释
CLOSE_WAIT过多的原因(被动方应用未 close) - 能对比 TCP 与 QUIC/HTTP3 的连接建立差异