Skip to content

TCP 三次握手与四次挥手

握手挥手流程、状态变化、常见问题。

Updated View as Markdown
For humans

TCP 三次握手与四次挥手

TCP 连接建立和关闭的完整流程,面试必考。主线:为什么三次、为什么四次、状态机、异常场景。

三次握手

三次握手: 双方确认收发能力

步骤 报文 证明
1 SYN(seq=x) 客户端发送能力
2 SYN+ACK(seq=y, ack=x+1) 服务端收发能力 + 确认收到
3 ACK(ack=y+1) 客户端确认收到

为什么不是两次:两次无法确认“客户端的接收能力”(服务端发了 SYN+ACK 但不知道客户端收没收到)。三次是最少次数,让双方都确认对方收发正常。

为什么不是四次:第二次可以合并(SYN+ACK 一起发),三次足够。

序列号的意义:seq 是数据流的起始序号,ack = 对方 seq + 1。序列号让 TCP 能排序、去重、可靠传输(见可靠传输篇)。

四次挥手

四次挥手: 两个方向分别关闭

为什么四次:TCP 是全双工,两个方向独立关闭。主动方发 FIN 只是关闭自己发送方向,被动方可能还有数据要发,所以 ACK 和 FIN 不能合并(和握手的 SYN+ACK 可合并不同)。

状态机关键点

状态 场景
LISTEN 服务端等待连接
SYN_SENT / SYN_RCVD 握手中间态
ESTABLISHED 正常通信
FIN_WAIT_1/2 主动关闭方等待
TIME_WAIT 主动关闭方停留 2MSL
CLOSE_WAIT 被动关闭方等应用 close

TIME_WAIT(必考):主动关闭方收到 FIN 回 ACK 后等 2MSL(报文最大生存时间 × 2):

  • 保证末尾的 ACK 能到达(丢了对方重发 FIN,还能响应)
  • 保证旧连接报文在网络中消失,不污染新连接
  • 代价:大量短连接时 TIME_WAIT 堆积占端口(高并发服务要处理,见下)

CLOSE_WAIT 堆积:被动关闭方收到 FIN 但应用没调用 close(代码 bug),连接泄漏。netstat 看到大量 CLOSE_WAIT 就是应用没关连接。

常见问题

现象 原因
大量 TIME_WAIT 短连接服务端主动关闭(配 keep-alive 减少)
大量 CLOSE_WAIT 应用未 close(代码 bug)
半连接队列满 SYN 洪水 / 并发太高,listen backlog 调优
连接超时 防火墙丢包、对端不响应(SYN 重试)

面试追问

  1. 为什么三次握手? 最少次数让双方确认对方收发正常。两次确认不了客户端接收能力
  2. 为什么四次挥手? 全双工:两个方向独立关。被动方 ACK 和 FIN 不能合并(可能还有数据)
  3. TIME_WAIT 为什么等 2MSL? 保证末尾 ACK 可达(防重发 FIN)和旧报文消失(防污染新连接)
  4. CLOSE_WAIT 多说明什么? 应用收到 FIN 没 close:连接泄漏 bug。排查代码
  5. 握手丢包怎么办? 超时重传 SYN/SYN+ACK(指数退避)。连接超时通常是对端或防火墙问题
Navigation

Type to search…

↑↓ navigate↵ selectEsc close