TCP连接TIME_WAIT和CLOSE_WAIT状态

TCP协议的三次握手和四次挥手:

注:seq:"sequance"序列号;ack:"acknowledge"确认号;SYN:"synchronize"请求同步标志;;ACK:"acknowledge"确认标志";FIN:"Finally"结束标志。

  TCP连接建立过程:首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源。Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了。

  TCP连接断开过程:假设Client端发起中断连接请求,也就是发送FIN报文。Server端接到FIN报文后,意思是说"我Client端没有数据要发给你了",但是如果你还有数据没有发送完成,则不必急着关闭Socket,可以继续发送数据。所以你先发送ACK,"告诉Client端,你的请求我收到了,但是我还没准备好,请继续你等我的消息"。这个时候Client端就进入FIN_WAIT状态,继续等待Server端的FIN报文。当Server端确定数据已发送完成,则向Client端发送FIN报文,"告诉Client端,好了,我这边数据发完了,准备好关闭连接了"。Client端收到FIN报文后,"就知道可以关闭连接了,但是他还是不相信网络,怕Server端不知道要关闭,所以发送ACK后进入TIME_WAIT状态,如果Server端没有收到ACK则可以重传。“,Server端收到ACK后,"就知道可以断开连接了"。Client端等待了2MSL后依然没有收到回复,则证明Server端已正常关闭,那好,我Client端也可以关闭连接了。Ok,TCP连接就这样关闭了!

1 TCP连接中的状态

TCP连接TIME_WAIT和CLOSE_WAIT状态_第1张图片 
图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状态。

TCP连接TIME_WAIT和CLOSE_WAIT状态_第2张图片 
图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维持的时间过短?

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

TCP连接TIME_WAIT和CLOSE_WAIT状态_第3张图片 
图3 TIME-WAIT状态连接被快速回收

2 当最后一个ACK丢失时,远程连接进入LAST-ACK状态,它可以确保远程已经关闭当前TCP连接。如果没有TIME-WAIT状态,当远程仍认为这个连接是有效的,则会继续与其通讯,导致这个连接会被重新打开。当远程收到一个SYN 时,会回复一个RST包,因为这SEQ不对,那么新的连接将无法建立成功,报错终止。如图4所示: 
TCP连接TIME_WAIT和CLOSE_WAIT状态_第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信号。换句话说,就是在对方连接关闭之后,程序里没有检测到,或者程序压根就忘记了这个时候需要关闭连接,于是这个资源就一直 
被程序占着。


你可能感兴趣的:(计算机网络)