题目
为什么需要 TIME_WAIT 状态?
答案
**主动发起断开连接的一方才会有 TIME_WAIT 状态**。而被动断开连接的一方在收到最后一个 ACK 报文后就会直接进入 Closed 状态。
TIME_WAIT 状态存在有两个原因
1)**等待可能延迟的 ACK 报文**。如果第四次握手即最后一个 ACK 报文因为网络原因丢失,服务端会因为没有收到 ACK 而超时重传 FIN 报文,处于 TIME_WAIT 状态的客户端可以继续对 FIN 报文做回复,向服务端发送 ACK 报文
假设客户端【没有】TIME_WAIT 状态,而是在发完最后一次回 ACK 报文就直接进入 CLOSED 状态,如果该 ACK 报文丢失了,服务端则重传的 FIN 报文,而这时客户端已经进入到关闭状态了,在收到服务端重传的 FIN 报文后,就会回 RST 报文。
服务端收到这个 RST 并将其解释为一个错误(Connection reset by peer),这对于一个可靠的协议来说不是一个优雅的终止方式

2)**保证让迟来的 TCP 报文有足够的时间被识别和丢弃**。连接结束了,网络中的延迟报文也应该被丢弃掉,以免影响立刻建立的新连接。
假设 TIME-WAIT 没有等待时间或时间过短,举个例子:
- 服务端在关闭连接之前发送的 `SEQ = 301` 报文,被网络延迟了。
- 接着,服务端以相同的四元组重新打开了新连接,前面被延迟的 `SEQ = 301` 这时抵达了客户端,而且该数据报文的序列号刚好在客户端接收窗口内,因此客户端会正常接收这个数据报文,但是这个数据报文是上一个连接残留下来的,这样就产生数据错乱等严重的问题。
为了防止历史连接中的数据,被后面相同四元组的连接错误的接收,因此 TCP 设计了 TIME_WAIT 状态,状态会持续 `2MSL` 时长,这个时间**足以让两个方向上的数据包都被丢弃(序列号对不上就会被丢弃),使得原来连接的数据包在网络中都自然消失,再出现的数据包一定都是新建立连接所产生的。**
