LAST_ACK :当被动关闭的一方在发送FIN报文后,等待对方的ACK报文的时候,就处于LAST_ACK 状态。当收到对方的ACK报文后,也就可以进入到CLOSED 可用状态了。
TCP 的 Peer 两端同时断开连接由上面的”TCP协议状态机 “图可以看出
TCP的Peer端在收到对端的FIN包前 发出了FIN包,那么该Peer的状态就变成了FIN_WAIT1
Peer在FIN_WAIT1状态下收到对端Peer对自己FIN包的ACK包的话,那么Peer状态就变成FIN_WAIT2,
Peer在FIN_WAIT2下收到对端Peer的FIN包,在确认已经收到了对端Peer全部的Data数据包后,就响应一个ACK给对端Peer,然后自己进入TIME_WAIT状态。
但是如果Peer在FIN_WAIT1状态下首先收到对端Peer的FIN包的话,那么该Peer在确认已经收到了对端Peer全部的Data数据包后,就响应一个ACK给对端Peer,然后自己进入CLOSEING状态,Peer在CLOSEING状态下收到自己的FIN包的ACK包的话,那么就进入TIME WAIT 状态。于是
TCP的Peer两端同时发起FIN包进行断开连接,那么两端Peer可能出现完全一样的状态转移 FIN_WAIT1——>CLOSEING——->TIME_WAIT,也就会Client和Server最后同时进入TIME_WAIT状态
TCP 的 TIME_WAIT 状态要说明TIME_WAIT的问题,需要解答以下几个问题:
Peer两端,哪一端会进入TIME_WAIT呢?为什么?
相信大家都知道,TCP主动关闭连接的那一方会最后进入TIME_WAIT。
那么怎么界定主动关闭方呢?
是否主动关闭是由FIN包的先后决定的,就是在自己没收到对端Peer的FIN包之前自己发出了FIN包,那么自己就是主动关闭连接的那一方。对于TCP 的 Peer 两端同时断开连接 描述的情况,那么Peer两边都是主动关闭的一方,两边都会进入TIME_WAIT。为什么是主动关闭的一方进行TIME_WAIT呢,被动关闭的进入TIME_WAIT可以不呢?
我们来看看TCP四次挥手可以简单分为下面三个过程
过程一.主动关闭方 发送FIN;
过程二.被动关闭方 收到主动关闭方的FIN后 发送该FIN的ACK,被动关闭方发送FIN;
过程三.主动关闭方 收到被动关闭方的FIN后发送该FIN的ACK,被动关闭方等待自己FIN的ACK问题就在过程三中,据TCP协议规范,不对ACK进行ACK。
如果主动关闭方不进入TIME_WAIT,那么主动关闭方在发送完ACK就走了的话:如果最后发送的ACK在路由过程中丢掉了,最后没能到被动关闭方,这个时候被动关闭方 没收到自己FIN的ACK就不能关闭连接,接着被动关闭方 会超时重发FIN包,但是这个时候已经没有对端会给该FIN回ACK,被动关闭方就无法正常关闭连接了,所以主动关闭方需要进入TIME_WAIT 以便能够重发丢掉的被动关闭方FIN的ACK。
TIME_WAIT状态为什么需要经过2MSL的时间才关闭连接呢?
为了保证A发送的最后一个确认报文段能够到达B。这个确认报文段可能会丢失,如果B收不到这个确认报文段,其会重传第三次“挥手”发送的FIN+ACK报文,而A则会在2MSL时间内收到这个重传的报文段,每次A收到这个重传报文段后,就会重启2MSL计时器。这样可以保证A和B都能正常关闭连接。
为了防止已失效的报文段出现在下一次连接中。A经过2MSL时间后,可以保证在本次连接中传输的报文段都在网络中消失,这样一来就能保证在后面的连接中不会出现旧的连接产生的报文段了。
TIME_WAIT状态是用来解决或避免什么问题呢?
TIME_WAIT主要是用来解决以下几个问题:
上面解释为什么主动关闭方需要进入TIME_WAIT状态中提到的: 主动关闭方需要进入TIME_WAIT 以便能够重发丢掉的被动关闭方FIN的ACK。如果主动关闭方不进入TIME_WAIT,那么在主动关闭方对被动关闭方FIN包的ACK丢失了的时候,被动关闭方由于没收到自己FIN的ACK,会进行重传FIN包,这个FIN包到主动关闭方后,由于这个连接已经不存在于主动关闭方了,这个时候主动关闭方无法识别这个FIN包,协议栈会认为对方疯了,都还没建立连接你给我来个FIN包?于是回复一个RST包给被动关闭方,被动关闭方就会收到一个错误(我们见的比较多的:connect reset by peer,这里顺便说下 Broken pipe,在收到RST包的时候,还往这个连接写数据,就会收到 Broken pipe错误了),原本应该正常关闭的连接,给我来个错误,很难让人接受。