文章目录
描述下TCP网络建立连接的过程

描述下TCP网络断开连接的过程

- TCP 断开连接通常通过
四次挥手完成。假设客户端主动关闭连接。- 第一步,客户端调用
close(),向服务端发送FIN报文,表示客户端这边已经没有数据要发送了,然后客户端进入FIN_WAIT_1状态。 - 第二步,服务端收到
FIN后,会先回复一个ACK,表示已经知道客户端不再发送数据了。此时服务端进入CLOSE_WAIT状态,客户端收到这个ACK后进入FIN_WAIT_2状态。这里要注意,TCP 是全双工协议,客户端不发数据了,不代表服务端也没有数据要发。所以服务端收到客户端的FIN后,不能马上也关闭连接,它可能还要继续把剩余数据发送给客户端。 - 第三步,等服务端数据发送完毕后,服务端也会发送一个
FIN报文,表示服务端这边也没有数据要发送了,然后进入LAST_ACK状态。 - 第四步,客户端收到服务端的
FIN后,回复最后一个ACK,然后进入TIME_WAIT状态。服务端收到这个ACK后进入CLOSED状态。客户端等待2MSL后,也进入CLOSED状态。
- 第一步,客户端调用
所以四次挥手的本质是:分别关闭 TCP 双向数据流。客户端关闭发送方向,服务端确认;服务端关闭发送方向,客户端确认。
客户端为什么要等2MSL,此时服务端是一个什么状态,重发FIN的间隔时间
- 客户端发送最后一个
ACK后,会进入TIME_WAIT,并等待2MSL。这里主要有两个目的:- 第一,如果最后一个
ACK丢失,服务端会停留在LAST_ACK状态并重传FIN,客户端在TIME_WAIT中还能再次回复ACK,保证服务端能正常关闭; - 第二,等待
2MSL可以让旧连接中残留在网络里的报文过期,避免相同四元组的新连接收到旧报文。
- 第一,如果最后一个
TCP 连接由四元组唯一确定:源 IP + 源端口 + 目的 IP + 目的端口
如果客户端关闭后,立刻用同样的四元组建立新连接,那么网络中残留的旧报文可能会被新连接错误接收。
所以客户端等待 2MSL,是为了让旧连接中可能残留在网络里的报文全部过期。
MSL 是 Maximum Segment Lifetime,表示一个 TCP 报文在网络中的最大存活时间。
第 1 个 MSL:保证客户端最后发出的 ACK 最多存活这么久
第 2 个 MSL:如果 ACK 丢失,服务端重传的 FIN 最多再存活这么久
也就是说 2MSL 覆盖了这样一个最坏情况:
客户端最后 ACK 丢失
↓
服务端等待一段时间后重传 FIN
↓
这个重传 FIN 又在网络中存活最长时间
↓
客户端仍然能收到 FIN 并重新 ACK
客户端等待 2MSL 后,基本可以认为:1、旧连接相关报文已经从网络中消失;2、服务端如果要重传 FIN,也已经有机会被客户端处理
- 此时服务端的状态要分情况看:
- 如果最后一个
ACK正常到达,服务端会从LAST_ACK进入CLOSED; - 如果最后一个
ACK丢失,服务端会停留在LAST_ACK,并按照 TCP 的RTO重传机制重发FIN。
- 如果最后一个
FIN的重传间隔不是2MSL,而是由RTO控制,通常会根据RTT估算并进行指数退避。所以2MSL是客户端TIME_WAIT的保活时间,RTO才是服务端FIN重传的时间依据,这两个概念不能混在一起。
MSL取值多少
RFC 793中假设的MSL是2分钟,所以理论上TIME_WAIT = 2MSL = 4 分钟。- 但实际操作系统不一定按这个值实现。比如 Linux 中常见的
TIME_WAIT时间大约是60 秒,可以理解为实际采用了约30 秒 MSL的效果。Windows 默认场景下常见是2MSL = 4 分钟,也就是MSL约120 秒。