主动发起关闭连接的一方,才会有 TIME-WAIT 状态。
需要 TIME-WAIT 状态,主要是两个原因:
- 防止具有相同「四元组」的「旧」数据包被收到;
- 保证「被动关闭连接」的⼀方能被正确的关闭,即保证最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。
TCP 四元组可以唯⼀的确定⼀个连接,四元组包括如下:
- 源地址
- 源端⼝
- ⽬的地址
- ⽬的端⼝
原因⼀:防止旧连接的数据包
假设 TIME-WAIT 没有等待时间或时间过短,被延迟的数据包抵达后会发⽣什么呢?
如上图黄色框框服务端在关闭连接之前发送的 SEQ = 301 报文,被网络延迟了。
这时有相同端口的 TCP 连接被复用后,被延迟的 SEQ = 301 抵达了客户端,那么客户端可能会正常接收这个过期的报文,这就会产生数据错乱等严重的问题。
所以,TCP 就设计出了⼀个机制,经过 2MSL 这个时间,⾜以让两个方向上的数据包都被丢弃,使得原来 连接的数据包在⽹络中都⾃然消失,再出现的数据包⼀定都是新建立连接所产生的。
原因二:保证连接正确关闭
TIME-WAIT 作⽤是等待足够的时间以确保最后的 ACK 能让被动关闭方接收,从而帮助其正常关闭。
假设 TIME-WAIT 没有等待时间或时间过短,断开连接会造成什么问题呢?
如图红色框客户端四次挥手的最后⼀个 ACK 报文如果在网络中被丢失了,此时如果客户端 TIME-WAIT 过短或没有,则就直接进入了 CLOSED 状态了,那么服务端会⼀直处在 LASE_ACK 状态。
当客户端发起建立连接的 SYN 请求报文后,服务端会发送 RST 报文给客户端,连接建立的过程就会被终止。
如果 TIME-WAIT 等待足够长的情况就会遇到两种情况:
- 服务端正常收到四次挥手的最后⼀个 ACK 报文,则服务端正常关闭连接。
- 服务端没有收到四次挥手的最后⼀个 ACK 报文时,则会重发 FIN 关闭连接报文并等待新的 ACK 报文。
所以客户端在 TIME-WAIT 状态等待 2MSL 时间后,就可以保证双方的连接都可以正常的关闭。