TCP 四次挥手详解

TCP 四次挥手详解:为什么必须四次?为什么需要 TIME_WAIT?

1. 四次挥手的必要性

TCP 是全双工协议,数据可以双向独立传输。因此,关闭连接需要分别关闭 客户端→服务端服务端→客户端 两个方向的数据流。四次挥手的设计确保了双方都能安全、有序地终止连接。

四次挥手流程:

  1. 第一次挥手(FIN)
    • 主动关闭方(如客户端)发送 FIN=1, seq=u,表示自己不再发送数据,进入 FIN_WAIT_1 状态。
  2. 第二次挥手(ACK)
    • 被动关闭方(如服务端)收到 FIN 后,回复 ACK=1, ack=u+1,进入 CLOSE_WAIT 状态。
    • 客户端收到 ACK 后进入 FIN_WAIT_2 状态(此时 客户端→服务端方向已关闭,但服务端仍可发送数据)。
  3. 第三次挥手(FIN)
    • 服务端完成数据发送后,发送 FIN=1, seq=v, ack=u+1,进入 LAST_ACK 状态。
  4. 第四次挥手(ACK)
    • 客户端收到 FIN 后,回复 ACK=1, ack=v+1,进入 TIME_WAIT 状态,等待 2MSL 后关闭连接。
    • 服务端收到 ACK立即关闭连接

2. 为什么不能合并为三次挥手?

如果尝试合并第二次和第三次挥手(即服务端在收到 FIN 后立即回复 FIN+ACK),会导致:

  • 数据丢失风险:服务端可能仍有未发送完的数据,强制关闭会导致数据不完整。
  • 破坏半关闭(Half-Close):TCP 允许一方在停止发送后仍能接收数据(如客户端关闭写入但仍可读服务端的响应)。

因此,四次挥手是可靠关闭的最小交互次数。


3. 为什么客户端需要 TIME_WAIT 状态?

客户端(主动关闭方)在发送最后一个 ACK 后进入 TIME_WAIT,等待 2MSL(Maximum Segment Lifetime) 后才关闭。原因:

(1) 确保最后一个 ACK 到达服务端
  • 如果客户端的 ACK 丢失,服务端会重传 FIN
  • 处于 TIME_WAIT 的客户端能响应重传的 FIN,重新发送 ACK,避免服务端卡在 LAST_ACK 状态。
(2) 避免旧连接的数据包干扰新连接
  • 网络中可能残留旧连接的延迟报文(相同四元组:源/目的 IP + 端口)。
  • TIME_WAIT 确保所有旧报文在网络中消亡(MSL 是报文最大生存时间),防止新连接收到脏数据。

为什么是 2MSL?

  • 1MSL 确保 ACK 到达服务端 + 1MSL 确保服务端重传的 FIN 到达客户端。
  • 通常 MSL 为 30 秒(Linux)或 2 分钟(Windows),因此 TIME_WAIT 持续 60 秒或 4 分钟。

4. 常见误解澄清
  1. "服务端为什么能立即关闭,而客户端要等待?"

    • 服务端是被动关闭方,收到最后一个 ACK 后无需等待,因为它的 FIN 已被确认。
    • 客户端是主动关闭方,需确保 ACK 不丢失(否则服务端会一直重传 FIN)。
  2. "可以优化为三次挥手吗?"

    • 不能!合并 ACKFIN 会牺牲可靠性(如服务端未发送完的数据会被丢弃)。
  3. "TIME_WAIT 是多余的?"

    • 不是!它是 TCP 可靠性的关键设计,避免连接混乱和资源泄漏。

5. 总结
  • 四次挥手 是 TCP 全双工特性的必然要求,确保双向数据流独立关闭。
  • TIME_WAIT 是主动关闭方的容错机制,解决 ACK 丢失和旧报文干扰问题。
  • 设计目标:在网络不可靠的条件下,实现连接的可靠释放

通过四次挥手和 TIME_WAIT,TCP 实现了优雅而安全的连接终止。

相关推荐
小毛驴8505 分钟前
WebSocket 在多线程环境下处理 Session并发
网络·websocket·网络协议
发发发发88814 分钟前
leetcode 415.字符串相加
linux·服务器·leetcode
乌恩大侠15 分钟前
USRP 毫米波通信解决方案
网络·5g·fpga开发
weixin_4380774935 分钟前
langchain入门笔记02:几个实际应用
服务器·langchain·rag
jingfeng5141 小时前
浅谈对linux进程池的理解
linux·运维·服务器
西阳未落2 小时前
Linux(17)——Linux进程信号(下)
linux·运维·服务器
白露与泡影2 小时前
彻底解决SpringCloud TCP连接过多未释放问题~
tcp/ip·spring·spring cloud
电商数据girl2 小时前
关于私域电商网站,接入电商API数据接口示例
运维·开发语言·网络·python·json·php
卑微的小鬼2 小时前
Cookie和Session是什么?有什么区别?
服务器·网络协议
哈基米喜欢哈哈哈3 小时前
Netty入门(二)——网络传输
java·开发语言·网络·后端