TCP状态转换图
相信大家这张图也很熟悉了
这里也是记录一下自己的理解:
在客户端处于FIN_WAIT_1时,正常情况是等待接收服务端发送的ACK报文,进入FIN_WAIT_2状态,接着等待接收服务器发送的FIN报文,之后客户端发送ACK报文,转向TIME_WAIT状态。
有两个例外:
①收到FIN报文,没有收到ACK,也就是说客户端在发送FIN报文后,还未收到服务器的ACK报文就已经收到了FIN报文,相当于双方同时关闭,进入CLOSING状态,此时只要收到对方的ACK报文,即可转入TIME_WAIT状态。
②收到FIN报文的同时也收到ACK报文,说明服务端也没有数据发送了,直接关闭,所以此时客户端发送完ACK后,不用转向FIN_WAIT_2状态,直接转到TIME_WAIT状态。
刚刚讨论的是下边FIN_WAIT_1的部分。接着讨论上半部分。
主要看细实线,也就是非正常转化部分。
首先是服务器端,LISTEN状态时,主动发送SYN报文,此时自己也会变成客户端,进入SYN_SENT状态。
SYN_SENT状态一般而言是客户端,它有两种特殊转换:
①此时如果他收到服务器端主动发来的SYN,那么他要回复SYN,ACK,同时状态转向SYN_RCVD,也就是服务器和客户端同时打开。
②如果发送了SYN报文之后遇到程序关闭或者超时,会转入CLOSED状态(如下图所述情况)
SYN_RCVD一般而言是服务端,如果他主动发出FIN报文,那么他会成主动结束的一方,发送完FIN之后,进入FIN_WAIT_1状态。
顺便加一下TIME_WAIT状态的必要性:
①发送最后的ACK报文时,可能会丢失,导致服务器没有收到ACK报文,依旧处于LAST_ACK状态,此时服务器会要求客户端重传ACK报文,如果客户端不等待2MSL,而是直接关闭连接,那么会回复一个复位报文,而这并不是服务器想要的。
②一个端口不能同时被打开多次,所以当TCP连接处于TIME_WAIT状态时,我们无法立刻利用这个端口建立一个新的连接。可以避免新连接收到老连接的一些迟到的报文。