TCP 三次握手与四次挥手

TCP 连接建立与断开的完整过程和状态变化

问题

TCP 三次握手与四次挥手的详细过程、状态变化,以及为什么是三次握手和四次挥手。

解答

三次握手(建立连接)

客户端                                服务端
  |                                    |
  |  -------- SYN, seq=x -------->     |
  |  (SYN_SENT)                        |
  |                            (SYN_RCVD)
  |  <--- SYN+ACK, seq=y, ack=x+1 ---  |
  |                                    |
  |  -------- ACK, ack=y+1 ------->    |
  |  (ESTABLISHED)           (ESTABLISHED)

过程说明:

  1. 第一次握手:客户端发送 SYN 报文(seq=x),进入 SYN_SENT 状态
  2. 第二次握手:服务端收到后,发送 SYN+ACK 报文(seq=y, ack=x+1),进入 SYN_RCVD 状态
  3. 第三次握手:客户端发送 ACK 报文(ack=y+1),双方进入 ESTABLISHED 状态

为什么是三次握手?

两次不行的原因:

场景:客户端发送的旧 SYN 报文延迟到达

客户端                                服务端
  |                                    |
  |  -------- 旧 SYN -------->         |  (延迟到达的历史报文)
  |                                    |
  |  <------- SYN+ACK --------         |  服务端以为要建立连接
  |                                    |
  |  (客户端发现是旧连接,不理会)        |  服务端白白等待,浪费资源

三次握手的作用:

  • 防止历史连接初始化(客户端可以通过第三次握手拒绝)
  • 同步双方的初始序列号(ISN)
  • 确认双方的收发能力都正常

四次挥手(断开连接)

客户端                                服务端
  |                                    |
  |  -------- FIN, seq=u -------->     |
  |  (FIN_WAIT_1)                      |
  |                            (CLOSE_WAIT)
  |  <------- ACK, ack=u+1 -------     |
  |  (FIN_WAIT_2)                      |
  |                                    |
  |         (服务端可能还有数据要发送)    |
  |                                    |
  |  <------- FIN, seq=w --------      |
  |                            (LAST_ACK)
  |  -------- ACK, ack=w+1 ------->    |
  |  (TIME_WAIT)               (CLOSED)|
  |                                    |
  |  等待 2MSL 后                       |
  |  (CLOSED)                          |

过程说明:

  1. 第一次挥手:客户端发送 FIN,进入 FIN_WAIT_1
  2. 第二次挥手:服务端发送 ACK,进入 CLOSE_WAIT,客户端进入 FIN_WAIT_2
  3. 第三次挥手:服务端发送 FIN,进入 LAST_ACK
  4. 第四次挥手:客户端发送 ACK,进入 TIME_WAIT,服务端收到后进入 CLOSED

为什么是四次挥手?

TCP 是全双工通信,每个方向的关闭需要单独进行:

三次握手时:SYN 和 ACK 可以合并发送(服务端同时发 SYN+ACK)

四次挥手时:ACK 和 FIN 不能合并
- 收到 FIN 只表示对方不再发送数据
- 但自己可能还有数据没发完
- 所以先回 ACK,等数据发完再发 FIN

TIME_WAIT 为什么等待 2MSL?

MSL(Maximum Segment Lifetime)是报文最大生存时间。

  • 确保最后的 ACK 能到达服务端(如果丢失,服务端会重发 FIN)
  • 让本次连接的所有报文在网络中消失,避免影响新连接

关键点

  • 三次握手:防止历史连接、同步序列号、确认双方收发能力
  • 四次挥手:TCP 全双工,每个方向单独关闭,ACK 和 FIN 不能合并
  • TIME_WAIT 等待 2MSL:确保 ACK 到达 + 旧报文消失
  • 握手用 SYN,挥手用 FIN,都需要消耗一个序列号
  • 服务端 CLOSE_WAIT 状态堆积通常是应用层没有正确关闭连接