TCP状态转换在《Linux 高性能服务器编程》中,有如下状态转换图。TCP的各个状态客户端建立连接(三次握手)SYN_SENT客户端发送完第一个同步报文段(第一次握手)后,就会进入这个状态。ESTABLISHED在收到服务器发送的确认和同步报文后(第二次握手),客户端只需要发送确认报文(第三次握手),即使三次握手完成,客户端也认为连接已建立.断开连接(四次挥手)FIN_WAIT_1TCP断开连接时,需要四次挥手。当客户端主动关闭连接并发送第一个FIN报文段(firstwave)时,进入该状态。FIN_WAIT_2服务器收到第一个FIN报文段后,回复客户端确认报文段状态(第二次挥手)。其实FINE_WAIT的意思就是等待服务器发送的FIN段。TIME_WAIT客户端收到服务器的FIN报文后(第三次挥手),返回服务器确认报文段(第四次挥手)。服务器建立连接(三次握手)CLOSED是假设的起点和终点,不是实际状态。LISTEN程序启动后,等待客户端连接状态。SYN_RCVD每次TCP连接建立时,都需要三次握手。该状态表示服务器已经收到客户端发送的同步报文段(第一次握手),并向客户端发送确认同步报文段(第二次握手后的状态),在该状态下,连接实际上经历了两次握手。ESTABLISHED收到客户端发送的确认报文段(第三次握手),即三次握手成功后,双方正式建立连接。断开连接(四手挥手)CLOSE_WAIT收到客户端主动断开连接的FIN报文段(第一手挥手)后,返回给客户端确认报文段状态(第二手挥手)。LAST_ACK服务器发送FIN报文段(第三次挥手)后的状态。在此状态之后,连接在收到确认段(第四次握手)后关闭。时序图相对于书上的状态转换图来说有些复杂和抽象。我根据自己的分析,画了一个时序图。建立连接(三次握手)断开连接(四次挥手)TIME_WAIT状态刚开始看到这个转换图的时候,我在想为什么会有TIME_WAIT状态呢?为什么不能直接达到CLOSED状态呢?相信很多人看到这张状态转移图都会有这样的疑惑。其实,造成这种情况的原因大致有两个。假设没有TIME_WAIT状态,可靠地终止连接。实际上,网络环境并不理想。在数据包传输的过程中,难免会出现一些延迟和丢包。如果客户端发送完最后一个确认报文段后,由于某种原因没有到达服务器,导致服务器超时后,会重新发送一个FIN报文段给客户端,请求重传。由于在客户端,连接实际上已断开,端口已关闭。然后,客户端收到这个报文段后,会向服务器发送一个RST报文段。服务器收到报文段后,会认为是错误的,期望收到的是确认报文段。确保延迟段有足够的时间进行处理同样在不利的网络环境中,一些数据包会在网络中延迟。如果没有TIME_WAIT状态,可能是关闭连接重新建立连接后才收到包。由于序号不同,客户端会要求服务器重传数据包,这样连接就会出现混乱和错误。TIME_WAIT状态的时间一般为2MAL时间,不释放端口。这样前一个连接的报文段就有足够的时间被识别或者丢弃,就不会出现这个问题。
