客户端状态的变化:
客户端创建套接字之后会connect服务器,这时客户端会发送一个SYN到服务器,状态转换到SYN_SENT并等待服务器的回复,收到服务端的回复SYN+ACK(同一个报文)之后???客户端会回复ACK此时状态转换到ESTABLISHED,正常数据交互完成之后客户端会close套接字此时发送一个FIN报文,状态转换到FIN_WAIT_1,同时等待服务端的回复,此时有三种情况:
(1)收到服务端的ACK但此时服务端没有关闭套接字。状态转换到了FIN_WAIT_2,然后再等待服务端关闭套接字发出的FIN,如果收到则回复ACK,状态转换到TIME_WAIT状态,等待2MSL超时之后自动转换为CLOSED状态。
?(2)服务端同时也在关闭套接字,此时客户端会收到SYN并发出ACK,状态转换到CLOSING,之后等待服务端回复ACK,若收到ACK则转到TIME_WAIT状态。
(3)服务器在收到客户端FIN之后立马关闭套接字,此时客户端会收到一个ACK和FIN并发出ACK,状态?转换到TIME_WAIT状态。
服务器状态的变化:
服务端?创建套接字之后调用listen函数将套接字有一个未连接的主动套接字转换为被动套接字,指示内核应接受指向该套接字的连接请求,套接字状态由CLOSE转换为LISTEN,等待客户端连接。所以服务端是被动接收连接的,服务端会先收到SYN,收到之后会立马发送一个SYN+ACK(同一个报文),此时状态转换到SYN_RCVD并等待客户端回复ACK,此时套接字处于未完成连接队列中,如果收到ACK状态会转换到ESTABLISHED,套接字处于已完成连接队列中,注意的是未完成连接队列和已完成连接队列之和不能超过listen设置的最大连接个数。这时服务端和客户端可以进行数据交互,客户端接收完数据之后主动close套接字,此时服务端会收到FIN并回复ACK,状态转换到LOSE_WAIT,当服务端的应用层也close套接字时服务端会发生一个FIN状态转换到LAST_ACK然后会收到客户端回复的ACK,状态转换到CLOSED。
为什么释放连接需要TIME_WAIT?
回忆一下我们最终的那个FIN与ACK,被动关闭方发送FIN,并等待主动关闭方返回的ACK。我们假设最终的ACK丢失,被动关闭方将需要重新发送它的最终那个FIN,主动关闭方必须维护状态信息(TIME_WAIT),以允许它重发最终的那个ACK。如果没有了这个状态,当他第二次收到FIN时,会响应一个RST(也是一种类型的TCP分节),会被服务器解释成一个错误。
目的:为了TCP打算执行必要的工作以彻底终止某个连接两个方向上的数据流(即全双工关闭),那么他必须要正确处理连接终止四个分节中任何一个分节丢失的情况
处于TIME_WAIT这个状态时,此套接字上的绑定了资源,将在2MSL(最大报文生存时间)内不可再使用。选择2MSL这个时间是为了避免出现上一次连接中被动关闭端重复发送的数据包。
我们假设ip1:port1和ip2:port2 之间有一个TCP连接。我们关闭了这个链接,过一段时间后在相同IP和端口之间建立了另一个连接。TCP必须防止来自之前那个连接的老的重复分组在新连接上出现。为了做到这一点,TCP将不复用处于TIME_WAIT状态的连接。2MSL的时间足以让某个方向上的分组存活MSL秒后被丢弃,另一个方向上的应答也最多存活MSL秒后被丢弃。
原文地址:https://www.cnblogs.com/single-dont/p/11386241.html