//加粗的线条是一般正常情况下的状态变迁图
正常情况:服务器端打开,客户端请求链接,三次握手后进入ESTABLISHED状态
客户端要关闭,4次挥手。
三次握手:
客服端:CLOSED(请求链接,发送SYN)->SYN_SENT(收到服务器端发送的SYN,ACK,客户端发送ACK)->ESTABLISHED
服务端:LISTEN(监听客户端请求)(收到客户端的SYN,发送ACK,SYN同意建立链接)->SYN收到(收到客户端的确认)->ESTABLISHED
客户端---------SYN------->服务端
客户端<-----ACK SYN-------服务端
客户端---------ACK------->服务端
四次挥手:
客户端:ESTABLISHED(发FIN)->FIN_WAIT_1->(收到服务器端的ACK确认)->FIN_WAIT_2->(客户端和服务端之间的管道是全双工,有两条,这时候关闭了一条,服务端发送FIN,客户端收到后发送ACK)->TIME_WAIT(2MSL超时关闭,默认服务端收到ACK,这时候两条管道都关闭了)
服务端:ESTABLISHED(收到客户端发送的FIN,发送ACK)->CLOSE_WAIT(客户端关闭了一条管道,这时候服务端发FIN)->LAST_ACK(等待最后确认关闭第二条管道)->(收到ACK,发送无)
客户端主动关闭情况 |
进程终止时所有打开的TCP连接上都会发出一个FIN |
客户端---------FIN-------->服务端
客户端<--------ACK---------服务端
/* 关闭了一条管道 */
客户端<--------FIN---------服务端
客户端---------ACK-------->服务端
/* 等待2MSL超时,关闭第二条管道 */
TIME_WAIT的持续时间是MSL(最长
生命周期Maximum Segment Lifttime)的2倍,2MSL,MSL一般情况是30S到2分钟,所以TIME_WAIT的时间一般为1~4分钟。
存在TIME_WAIT状态有两个理由: 1、实现终止TCP全双工连接的可靠性 假设最终的ACK丢失,服务器将重发最终的FIN,因此客户必须维护状态信息以允许它重发最终的ACK,如果不维护状态信息,它将响应以RST,而服务器则把该分节解释成一个错误。如果TCP打算执行所有必要的工作以彻底终止某个链接上两个方向的数据流,那么它必须能够处理连接终止序列四个分节中任何一个分节丢失的情况,也即主动关闭的那一端必须进入TIME_WAIT状态,因为它可能不得不重发最终的ACK。 2、允许老的重复分节在网络中消失 假设我们关闭某个TCP连接后,在以后的某个时候又重新建立相同的IP地址和端口之间的TCP连接。因为后一个连接和前一个连接它们的IP地址和端口号是相同的,TCP必须防止来自某个连接的老重复分组在连接终止后再现,从而被误解成属于同一个连接的化身。要实现这种功能,TCP不能给处于TIME_WAIT状态的连接启动新的化身,所有有TIME_WAIT,这段时间足够让某个方向上的分组最多存活MSL秒即被丢弃,另一个方向上的应答最多存活MSL秒也被丢弃。 |