TCP断开连接四次挥手

TCP 四次挥手是 TCP 协议断开连接的标准流程。因为 TCP 是一种全双工通信(双方可以同时收发数据)的协议,所以在断开连接时,通信双方的发送通道必须各自独立关闭,总共需要 4 次报文交互。

假设由客户端主动发起关闭请求,服务端被动响应,以下是四次挥手的详细步骤:

🌊 TCP 四次挥手完整流程

复制代码
客户端(主动断)                 服务端(被动断)
  ESTABLISHED                  ESTABLISHED
      |                            |
1.发 FIN=1 seq=u  -------------->  |
    进入 FIN_WAIT1                 |
                                   |
2.  <------------ ACK=1 ack=u+1  收FIN
                                   进入 CLOSE_WAIT
客户端收到ACK → 进入 FIN_WAIT2
                                   服务端继续发剩余数据
      |                            |
3.  <------------ FIN=1 seq=v     数据发完,主动关自己写通道
                                   进入 LAST_ACK
      |                            |
4.发 ACK=1 ack=v+1 --------------> |
进入 TIME_WAIT                     收到ACK → 进入 CLOSED
等待2MSL后客户端最终 CLOSED

第 1 次挥手:主动关闭方发送 FIN 报文

  • 动作 :客户端数据发送完毕,向服务端发送一个 FIN=1 的报文,表示"我没有数据要发了,请求关闭我这一侧的连接"。
  • 状态变化 :客户端从 ESTABLISHED(已建立连接)转变为 FIN_WAIT_1(等待终止)。

第 2 次挥手:被动关闭方回复 ACK

  • 动作 :服务端收到 FIN 后,立即回复一个 ACK 确认报文,表示"我知道你要关闭了"。
  • 状态变化 :服务端从 ESTABLISHED 转变为 CLOSE_WAIT(等待关闭);客户端收到确认后,从 FIN_WAIT_1 转变为 FIN_WAIT_2。
  • 注意:此时连接处于**半关闭(Half-Close)**状态。客户端不能再发数据,但可以接收数据;服务端如果还有剩余数据没发完,可以继续发给客户端。

第 3 次挥手:被动关闭方发送 FIN 报文

  • 动作 :当服务端的数据也全部发送完毕后,它会向客户端发送一个 FIN=1 的报文,表示"我也发完了,现在请求关闭我的发送通道"。
  • 状态变化 :服务端从 CLOSE_WAIT 转变为 LAST_ACK(最后确认)。

第 4 次挥手:主动关闭方回复 ACK

  • 动作 :客户端收到服务端的 FIN 后,回复最后一次 ACK 确认报文,表示"我知道了,连接正式关闭"。
  • 状态变化 :客户端进入 TIME_WAIT(时间等待)状态,等待一段时间后才会彻底释放资源;服务端收到这个 ACK 后,立刻进入 CLOSED(关闭)状态。

💡 核心问题解析

为什么握手是 3 次,而挥手是 4 次?

这是面试中非常经典的问题,核心原因在于 TCP 的全双工特性 以及 ACK 与 FIN 报文的分离:

  • 三次握手时:服务端收到客户端的连接请求(SYN)后,可以立刻把"同意连接"(ACK)和"我也要连接"(SYN)合并在同一个报文里发回去,节省了一次交互。
  • 四次挥手时 :当服务端收到客户端的关闭请求(FIN)时,它可能还有部分数据没有传输完成,不能立刻关闭自己的发送通道。因此,服务端必须先单独回复一个 ACK 告知"收到了",等自己真正处理完所有数据后,再单独发送一个 FIN 来请求关闭。这就导致无法合并,必须进行 4 次交互。
为什么主动关闭方最后要进入 TIME_WAIT 状态并等待 2MSL?

主动关闭方在发出最后一个 ACK 后,不会立刻关闭,而是会等待 2MSL(最长报文寿命的两倍)的时间,主要有两个作用:

  1. 保证最后一个 ACK 到达对方 :如果这个最后的 ACK 在网络中丢失了,服务端会因为超时重传第 3 次挥手的 FIN 报文。处于 TIME_WAIT 状态的客户端就能再次收到并重发 ACK,确保服务端能正常关闭。
  2. 防止旧连接的报文干扰新连接:等待 2MSL 可以让本次连接中所有滞留在网络中的残留报文自然失效消失,避免它们跑到下一次新建的连接中造成数据混乱。
  3. Linux 默认 MSL=30s,2MSL=60秒

总结:

  • 主动方:ESTABLISHED → FIN_WAIT1 → FIN_WAIT2 → TIME_WAIT → CLOSED
  • 被动方:ESTABLISHED → CLOSE_WAIT → LAST_ACK → CLOSED
相关推荐
小嘉丶学长2 小时前
Day14 · 字典与集合
java·开发语言·网络·python·学习·1024程序员节
LCG米2 小时前
STM32驱动W5500以太网模块实测:TCP吞吐瓶颈定位、TX指针回绕陷阱与断线重连保活落地
stm32·单片机·嵌入式硬件·tcp/ip
pt10434 小时前
Cisco设备网络安全系列-18:SIEM与SOAR安全解决方案
网络·安全
Tel199253080044 小时前
温度湿度信号转WiFi/MQTT/Modbus TCP采集模块 无线传输
网络·网络协议·tcp/ip·工业自动化·工控设备
yyuuuzz5 小时前
云服务器安全组规则优先级的机制记录
运维·服务器·网络·安全·阿里云·aws
youce_1235 小时前
测速跑满,但是打开网页、刷视频总转圈?问题不在带宽
网络·智能路由器
lazy H7 小时前
【计算机网络】第 13 篇:NAT 和端口映射是什么?为什么本地服务外网访问不了?
java·网络·网络协议·学习·计算机网络·408
Linux运维技术栈7 小时前
WAF部署在防火墙后面,获取不到真实IP怎么办?
服务器·网络·tcp/ip·安全·防火墙·waf
低慢小uav7 小时前
(已解决)Zynq芯片lwip协议栈,使用tcp作为服务器Service,接收大量数据时,长度接收正常,接收对数据校验,校验和异常分析
网络协议·tcp/ip·fpga开发
垆边人似月.7 小时前
RDMA项目踩坑(一):为什么最后一块数据必须使用实际长度?
网络·c/c++·rdma·高性能io·tcp与rdma