计算机网络——TCP四次挥手过程详解

上次写了TCP的三次握手,这次总结一下TCP的四次挥手的过程,理清楚为什么握手是三次,挥手需要四次。

TCP是面向连接的,连接的建立过程被称为“三次握手”,天下没有不散的宴席,有了连接的建立,就会有连接的断开,TCP断开的过程通常被称为“四次挥手”。

首先要明确一点,断开TCP请求既可以由客户端发起也可以由服务端发起。这里讨论客户端发起断开连接请求的情况。

过程如下:(可以先看文末的通俗对话模拟)

(1) 客户端A发出一个关闭连接的命令,这会使得客户端的TCP发送一个特殊的TCP报文段给服务器B,这个报文段的FIN标记位(finish的缩写,表示结束)被置为1。此时A由ESTABLISHED状态转为FIN_WAIT_1状态,等待来自B的ACK报文。

(2) B收到这个报文段,检测到这是请求关闭连接的报文,发送一个确认报文段(ACK字段为1)给A,表示收到,通知A可以释放连接了。A收到这个ACK报文时,单方面释放了与B的连接,此时他不能再向B发送应用层数据了,但由于B可能还有数据没有发送完,所以此时A还可以接收来自B的报文段。此时A进入FIN_WAIT_2状态,等待来自B的FIN报文。B由ESTABLISHED状态进入CLOSE_WAIT状态。

(3) 当B向A发送完所有数据之后,也向A发送一个关闭连接的报文段,FIN和ACK都为1的报文段(还没有搞清楚为什么ACK也是1,但估计是为了与第一次的请求关闭报文段区分开),并等待来自A的确认报文段。此时B进入LAST_ACK状态。

(4) A接收到B的关闭连接请求后,给B发一个确认报文段,通知B可以释放连接了。B收到之后,释放所有连接资源,进入CLOSED状态。而A并没有马上释放资源,而是进入TIME_WAIT状态,等待一段时间(自定义,通常为30sec、1min或2min),使得可以在ACK报文段丢失的情况下进行重传。在等待时间结束之后,连接正式关闭,客户端的所有资源也被释放,进入CLOSED状态。

以下分别为客户端和服务端的TCP连接状态转换(结合TCP的三次握手):

由上述的讨论可知,之所以需要进行四次挥手,在于某一方发起关闭连接的请求时,可以保证自己不再需要发送数据,但并不能猜测到对方是否已经发送完数据了,所以只是先通知对方我要断开连接了,你也差不多可以断开了,对方可以断开的时候则又会发一个断开连接的报文段。而额外的两个的ACK报文是确保两个FIN报文都被接收到。

模拟成一段对话就是:

  • A:“我发完数据了,不发了,要断开连接啦!”(FIN报文)
  • B:“好啊,你不发就不发,但先收完我发给你的数据好吗,很快就发完了。”(ACK报文)

(A继续接收来自B的数据)

  • B(发完数据):“好了,我也发完数据了,可以断开连接了!”(FIN/ACK报文)
  • A:“好,断开吧!”(ACK报文) (B收到后马上断开并释放资源,而A还要再等一会,万一这条消息丢失了,B还会再催促。等够一段时间,A就默认B已经收到确认消息了,于是也断开连接,释放资源)