TCP断开连接四次挥手
TCP 四次挥手是 TCP 协议断开连接的标准流程。因为 TCP 是一种全双工通信双方可以同时收发数据的协议所以在断开连接时通信双方的发送通道必须各自独立关闭总共需要 4 次报文交互。假设由客户端主动发起关闭请求服务端被动响应以下是四次挥手的详细步骤 TCP 四次挥手完整流程客户端(主动断) 服务端(被动断) ESTABLISHED ESTABLISHED | | 1.发 FIN1 sequ -------------- | 进入 FIN_WAIT1 | | 2. ------------ ACK1 acku1 收FIN 进入 CLOSE_WAIT 客户端收到ACK → 进入 FIN_WAIT2 服务端继续发剩余数据 | | 3. ------------ FIN1 seqv 数据发完主动关自己写通道 进入 LAST_ACK | | 4.发 ACK1 ackv1 -------------- | 进入 TIME_WAIT 收到ACK → 进入 CLOSED 等待2MSL后客户端最终 CLOSED第 1 次挥手主动关闭方发送 FIN 报文动作客户端数据发送完毕向服务端发送一个FIN1的报文表示“我没有数据要发了请求关闭我这一侧的连接”。状态变化客户端从ESTABLISHED已建立连接转变为FIN_WAIT_1等待终止。第 2 次挥手被动关闭方回复 ACK动作服务端收到FIN后立即回复一个ACK确认报文表示“我知道你要关闭了”。状态变化服务端从ESTABLISHED转变为CLOSE_WAIT等待关闭客户端收到确认后从FIN_WAIT_1转变为FIN_WAIT_2。注意此时连接处于**半关闭Half-Close**状态。客户端不能再发数据但可以接收数据服务端如果还有剩余数据没发完可以继续发给客户端。第 3 次挥手被动关闭方发送 FIN 报文动作当服务端的数据也全部发送完毕后它会向客户端发送一个FIN1的报文表示“我也发完了现在请求关闭我的发送通道”。状态变化服务端从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最长报文寿命的两倍的时间主要有两个作用保证最后一个 ACK 到达对方如果这个最后的ACK在网络中丢失了服务端会因为超时重传第 3 次挥手的FIN报文。处于TIME_WAIT状态的客户端就能再次收到并重发ACK确保服务端能正常关闭。防止旧连接的报文干扰新连接等待 2MSL 可以让本次连接中所有滞留在网络中的残留报文自然失效消失避免它们跑到下一次新建的连接中造成数据混乱。Linux 默认MSL30s2MSL60秒总结主动方ESTABLISHED→FIN_WAIT1→FIN_WAIT2→TIME_WAIT→CLOSED被动方ESTABLISHED→CLOSE_WAIT→LAST_ACK→CLOSED