优雅地说再见
不辞而别,总是容易让人猝不及防。当我们不得结束一段愉快的聊天,离开一个让人难以割舍的城市,你会怎么做?
当然是要学会,优雅地说再见了。
《礼貌地说你好——TCP协议三次握手》一文中已经介绍了,TCP协议是如何建立连接的。建立连接后,数据传输完成,我们又该如何优雅地关闭连接呢?
念念不忘——TCP的四次挥手
第一次挥手
客户端准备关闭连接时,则会向服务端发送FIN=1的数据包,并且进入FIN_WAIT_1状态。
第二次挥手
服务端收到客户端的FIN=1的数据包后,则会向客户端响应一个ACK数据包,并进入准备关闭连接的状态。服务端此时则会开始准备停止数据传输。
客户端收到服务端响应的ACK数据包后,则进入FIN_WAIT_2的状态。此时,仍然有可能存在数据传输,需要等待服务端真正停止数据传输时才能进入关闭状态。
第三次挥手
服务端处理完数据传输则会向客户端发送一个FIN数据包,并进入LASK_ACK状态,表示服务端已经进入连接关闭状态。
第四次挥手
客户端收到FIN数据包后,则可以确认数据传输已经完全停止,进入TIME_WAIT状态,并向服务端响应ACK数据包。等待2MSL(Maximum Segment Lifetime,最大报文生存时间)后,连接才真正关闭,进入CLOSE状态。
服务端接收到ACK数据包后则断开连接,进入CLOSE状态。
重试与容错
当FIN数据包发送出去后,长时间未收到ACK响应的数据包,都会触发超时重传。
客户端接受到FIN指令后为什么不是立即关闭连接,而要等待2MSL时间再关闭?
假设客户端没有TIME_WAIT的状态,而是里面关闭连接,此时如果客户端立马重新建立连接,连接建立成功后,又收到上一个关闭连接的数据包,并向服务端响应了ACK数据包,则会导致服务端的数据混乱。
总结
TCP协议关闭连接的时候,由于可能正在进行数据传输,客户端和服务端都会先进入等待关闭连接的过程。
当客户端或者服务端发送FIN数据包未在一定的时间内收到ACK响应包,则会进行重试。
客户端最后收到服务端的FIN数据包后,会先进入TIME_WAIT的状态等待2MSL(最大报文生存周期)。以防止,因为网络延迟,消息传输超时等问题导致的消息传输错乱的问题的发生。