TCP CLOSE流程
特征
u 发送一个FIN报文表示结束本端数据的发送,但是还可以接收数据,称之为半关闭
u TCP是一个全双工的协议,两端全部close才完成了一个连接的关闭;
u 首先发起close(发送FIN),我们称之为主动关闭,对端的close我们称为被动关闭;
u 同时关闭;
半关闭
发送一个FIN报文表示结束本端数据的发送,继续接收对端发送的数据的状态,我们称之为半关闭。通过调用shutdown可以实现这个目的。
主动关闭
前提
应用层知道连接的存在:1、客户端已经发起connect;2、服务器已经accept一个连接。
初品
在TCP各状态下,主动关闭时状态迁移分析:
1、 本端还没有收到对端的SYN报文报文(状态为CLOSED, LISTEN, SYN_SENT),直接释放TCP连接和SOCKET资源;
2、 本端已经接收到对端的SYN报文,但是之前没有关闭连接的动作(SYN_RCVD, ESTABLISHED状态),发送FIN报文给对端,状态转为FIN_WAIT_1;
3、 对端已经关闭连接(half-close),本端还没有关闭(CLOSE_WAIT状态),发送FIN报文给对端,状态转为LAST_ACK;
4、 本端已经发送FIN报文,连接还没有完全关闭(其他状态),保持状态不变,不做任何操作。
CLOSED |
LISTEN |
SYN_RCVD |
TIME_WAIT
|
CLOSING
|
FIN_WAIT_2 |
LAST_ACK
|
ESTABLISHED |
CLOSE_WAIT
|
FIN_WAIT_1 |
SYN_SENT |
细尝
情况1已经完成了关闭TCP连接的过程,情况3属于被动关闭,在后续章节再仔细分析,情况4没有改变状态,因此就情况2后的细节进行分析。
现在连接已经处于FIN_WAIT_1状态,那么:
1、 接收到FIN的ACK报文,进入FIN_WAIT_2状态,等待对端关闭连接;
2、 接收对端的FIN/ACK报文, 发送ACK,进入TIME_WAIT状态,2MSL时间后丢弃连接(先处理ACK,再处理FIN);
3、 接收到对端的FIN,回ACK,进入CLOSING状态(同时关闭,后续章节分析);
4、 FIN发送超时,连续若干次发送失败,丢弃连接;
5、 接收到对端的RST报文,丢弃连接。
CLOSED |
TIME_WAIT
|
CLOSING
|
FIN_WAIT_2 |
FIN_WAIT_1 |
① |
② |
③ |
④ |
深究
Ø FIN_WAIT_2状态
FIN_WAIT_2是一个等待状态,可能:
1、 对端仍有数据需要发送,等待接收对端的数据;
2、 对端发送FIN报文,回ACK,进入TIME_WAIT状态;
3、 对端因意外崩溃导致不能发送FIN报文过来,连接一直僵死到inactive超时为止;
如果在一个系统资源紧张的系统中,出现情况2是不可饶恕的问题。如何解决?启动2MSL定时器,在这段时间还没有接收到对端的FIN报文直接丢弃连接。
Ø 2MSL等待状态
概念:TIME_WAIT状态又成为 2MSL状态,一个主动关闭的连接在进入TIME_WAIT状态后,必须等待2MSL的时间后再关闭,防止最后发送的ACK丢失。
注意点:
1、2MSL是基于IP报文的跳数,而不是时间;
2、当TCP处于2MSL状态,不可以创建同一连接;
被动关闭
这里研究接收到对端发送过来的FIN报文处理的情况,包括但不限于被动关闭:
1、 本端没有发送和接收过FIN报文(SYN_RCVD、ESTABLISHED状态),回ACK,进入CLOSE_WAIT状态,等待应用程序关闭;
2、 本端已经发送过FIN报文但没有被确认(FIN_WAIT_1状态),进入CLOSING状态(同时关闭);
3、 本端已经发送过FIN报文并被确认(FIN_WAIT_2状态),进入TIME_WAIT状态;
4、 连接已主动关闭但没有丢弃(TIME_WAIT状态),说明对端没有收到ACK,重传ACK,并重启2MSL定时器;
5、 其他状态下不处理。
CLOSED |
LISTEN |
SYN_RCVD |
TIME_WAIT
|
CLOSING
|
FIN_WAIT_2 |
LAST_ACK
|
ESTABLISHED |
CLOSE_WAIT
|
FIN_WAIT_1 |
SYN_SENT |
总结
为了方便理解状态的变迁,不妨认为SYN报文表明发送者想发送数据,FIN报文表明发送者停止发送报文。所以SYN_SENT状态只能主动发送FIN,而SYN_RCVD状态下即可发送FIN,也可以接收FIN。
参考资料:
1、TCP/IP详解卷1:协议
2、TCP/IP详解卷2:实现