一句话说透计算机网络里面的tcp四次挥手的过程

254 阅读3分钟

一句话总结:
TCP四次挥手就像两人告别——先说要走(FIN),对方确认(ACK),等对方也说要走(FIN),最后再确认(ACK),确保双方都安心离开!


一、流程拆解(好友告别版)

假设你和朋友 可靠地 结束通话,步骤如下:

1. 第一次挥手(客户端 → 服务器)

  • 动作:你说:“我这边说完了,准备撤了! ”(发送 FIN 包)。
  • 意义:客户端主动关闭,进入 FIN_WAIT_1 状态,等待确认。

2. 第二次挥手(服务器 → 客户端)

  • 动作:朋友回答:“收到!但我还有点话要说... ”(回复 ACK 包)。
  • 意义:服务器确认收到关闭请求,进入 CLOSE_WAIT 状态,继续处理剩余数据。

3. 第三次挥手(服务器 → 客户端)

  • 动作:朋友说完后,也告别:“我也说完了,拜拜! ”(发送 FIN 包)。
  • 意义:服务器主动关闭,进入 LAST_ACK 状态,等待最后确认。

4. 第四次挥手(客户端 → 服务器)

  • 动作:你最后确认:“好的,彻底拜拜! ”(发送 ACK 包)。
  • 意义:客户端进入 TIME_WAIT 状态(等2倍报文寿命),确保对方收到ACK。

二、为什么必须四次?三次行不行?

关键点:TCP是全双工通信,每个方向独立关闭

  • 你的关闭(发FIN)和 对方的关闭(发FIN)是两件事,需分别确认。
  • 如果合并第二次和第三次挥手(ACK+FIN一起发),可能对方还有数据没传完!

三、技术细节(包结构)

  • 第一次挥手Flags=FIN, SEQ=序列号X
  • 第二次挥手Flags=ACK, ACK=X+1
  • 第三次挥手Flags=FIN+ACK, SEQ=序列号Y, ACK=X+1
  • 第四次挥手Flags=ACK, ACK=Y+1

示例

客户端 → 服务器:FIN(SEQ=100)  
服务器 → 客户端:ACK(ACK=101)  
(服务器处理剩余数据...)  
服务器 → 客户端:FIN+ACK(SEQ=300, ACK=101)  
客户端 → 服务器:ACK(ACK=301

四、关键状态解析

  1. TIME_WAIT(客户端)

    • 等待时长:2倍报文最大存活时间(2MSL,通常2分钟)。

    • 作用

      • 确保最后一个ACK送达,若丢失可重传。
      • 让旧连接的报文在网络中消亡,防止与新连接混淆。
  2. CLOSE_WAIT(服务器)

    • 问题场景:若代码未正确关闭连接,会导致大量 CLOSE_WAIT 堆积,占用资源。

五、常见问题解答

1. 为什么有时候连接关闭很慢?

  • 服务器未及时发FIN:可能还在处理数据或代码未正确调用 close()
  • 客户端卡在TIME_WAIT:需等待2MSL,可通过调整内核参数缩短。

2. 大量TIME_WAIT危害?

  • 占用端口资源:客户端端口耗尽,无法发起新连接。

  • 解决方案

    • 复用连接(HTTP Keep-Alive)。
    • 调整 net.ipv4.tcp_tw_reuse 参数。

3. 如果第四次挥手ACK丢了怎么办?

  • 服务器重传FIN:客户端在TIME_WAIT期间收到后,会重发ACK。

六、总结口诀

“四次挥手断连接,双向关闭要确认。
一FIN来二ACK,三FIN四ACK跟。
TIME_WAIT防丢包,CLOSE_WAIT查代码。
连接资源及时放,网络畅通无烦恼!”