TCP连接TIME_WAIT和CLOSE_WAIT状态

1 TCP连接中的状态

这里写图片描述
图1 TCP连接和断开的过程图

1.1 名词解释

状态 含义
LISTEN 服务器在等待进入呼叫
SYN_RECV 一个连接请求已经到达,等待确认
SYN_SENT 应用已经开始,打开一个连接
ESTABLISHED 连接已经建立,正常数据传输状态
FIN_WAIT1 连接一端(应用)完成数据传输,主动关闭
FIN_WAIT2 主动关闭一端收到另一端释放连接的确认
ITMED_WAIT 等待所有分组死掉
CLOSING 两边同时尝试关闭
TIME_WAIT 另一边已初始化一个释放
CLOSE_WAIT 连接一端被动关闭
LAST_ACK 等待所有分组死掉
CLOSED 无连接是活动的或正在进行

2 TIME_WAIT 状态

通信双方建立TCP连接后,主动关闭连接的一方就会进入TIME_WAIT状态。
注:有可能通信双方同时主动关闭连接!

如图2,客户端主动关闭连接时,会发送最后一个ack后,然后会进入TIME_WAIT状态,再停留2个MSL时间(后有MSL的解释),进入CLOSED状态。

这里写图片描述
图2 TCP关闭过程

2.1 为什么存在TIME_WAIT状态?

TCP这样设计的两个原因:

1. 可靠地实现TCP全双工连接的终止

TCP协议在关闭连接的四次握手过程中,最终的ACK是由主动关闭连接的一端(后面统称A端)发出的,如果这个ACK丢失,对方(后面统称B端)将重发出最终的FIN,因此A端必须维护状态信息(TIME_WAIT)允许它重发最终的ACK。如果A端不维持TIME_WAIT状态,而是处于CLOSED
状态,那么A端将响应RST分节,B端收到后将此分节解释成一个错误(在java中会抛出connection
reset的SocketException)。
因而,要实现TCP全双工连接的正常终止,必须处理终止过程中四个分节任何一个分节的丢失情况,主动关闭连接的A端必须维持TIME_WAIT状态 。

2. 允许老的重复segment在网络中消逝

TCP segment 可能由于路由器异常而“迷途”,在迷途期间,TCP发送端可能因确认超时而重发这个segment,迷途的segment在路由器修复后也会被送到最终目的地,这个迟到的迷途segment到达时可能会引起问题。在关闭“前一个连接”之后,马上又重新建立起一个相同的IP和端口之间的“新连接”,“前一个连接”的迷途重复分组在“前一个连接”终止后到达,而被“新连接”收到了。为了避免这个情况,TCP协议不允许处于TIME_WAIT状态的连接启动一个新的可用连接,因为TIME_WAIT状态持续2MSL,就可以保证当成功建立一个新TCP连接的时候,来自旧连接重复分组已经在网络中消逝。

2.2 TIME_WAIT状态存在时,维持的时间多长合理?

MSL就是maximum segment lifetime(最大分节生命期),这是一个IP数据包能在互联网上生存的最长时间,超过这个时间IP数据包将在网络中消失 。MSL在RFC 1122上建议是2分钟,而源自berkeley的TCP实现传统上使用30秒。

当主动关闭连接的A端在TIME_WAIT状态等待2MSL时间中, 如果对端B端未收到ACK则重发FIN报文,那么A端仍可以回复ACK。因此在2MSL时间中,如果A端没有收到B端的FIN报文,则表明B端正确接收ACK。

2.2.1 如果TIME_WAIT维持的时间过短?

1 缩短TIME-WAIT的时间后,延迟的TCP 包会被新建立的TCP连接接收。如图3所示:

这里写图片描述
图3 TIME-WAIT状态连接被快速回收

2 当最后一个ACK丢失时,远程连接进入LAST-ACK状态,它可以确保远程已经关闭当前TCP连接。如果没有TIME-WAIT状态,当远程仍认为这个连接是有效的,则会继续与其通讯,导致这个连接会被重新打开。当远程收到一个SYN 时,会回复一个RST包,因为这SEQ不对,那么新的连接将无法建立成功,报错终止。如图4所示:
这里写图片描述
图4 没有TIME_WAIT时

2.2.1 如果TIME_WAIT维持的时间过长?

主动关闭连接端迟迟无法关闭连接,占用程序资源。

2.3 RST报文的作用

使用RST报文跳过TIME_WAIT状态来释放一个连接

异常终止一个连接,可以通过发送一个RST报文段而不是FIN报文段来中途释放一个连接,收到RST的一方将终止该连接,并通知应用层连接复位。

3 CLOSE_WAIT状态

3.1 服务器程序一直保持CLOSE_WAIT状态

如果服务器程序TCP连接一直保持在CLOSE_WAIT状态,那么只有一种情况,就是在对方关闭连接之后服务器程序自己没有进一步发出ack信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直
被程序占着。

4 参考

1不要在linux上启用net.ipv4.tcp_tw_recycle参数
2 TCP/IP TIME_WAIT状态原理
3 服务器TIME_WAIT和CLOSE_WAIT详解和解决办法
4 The TCP/IP Guide
5 TCP连接流程图
TCP连接TIME_WAIT和CLOSE_WAIT状态_第1张图片
图5 TCP连接流程图
TCP连接TIME_WAIT和CLOSE_WAIT状态_第2张图片
图6 TCP详细流程图

你可能感兴趣的:(网络编程)