TCP释放连接-四次挥手

简介

TCP连接释放过程比较复杂,我们需要结合双方状态去理解。

四次挥手图

步骤

数据传输结束后,通信双方都可以释放连接。现在A和B都处于ESTABLISHED状态。步骤如下:

  • A的应用进程先向其TCP发出连接释放报文段,并停止发送数据,主动关闭TCP连接。A把连接释放报文段(FIN包)首部的终止控制位FIN = 1,其序号seq = u,它等于前面已传送过的数据的最后一个字节+1。这时A进入FIN-WAIT-1状态。注意,FIN报文段即使不携带数据,也要消耗一个序号
  • B收到连接释放报文段后立即发出确认,确认号ack = u + 1,这个报文段自己的 序号seq = v,等于B前面已传送过的数据的最后一个字节的序号+1。然后B就进入CLOSE-WAIT(关闭等待)状态。TCP服务器进程这时应通知高层应用进程,因而从A到B这个方向的连接就释放了,这时的TCP连接处于半关闭(half-close)状态,也就是A已经没有数据要发送了,但是B若发送数据,A仍要接收。也就是说,从B到A这个方向的连接并未关闭,这个状态可能会持续一些时间。
  • A接收来自B的确认后,就进入FIN-WAIT-2(终止等待2)状态,等待B发出的连接释放报文段。
  • 直到B已经没有要向A发送的数据,其应用进程就通知TCP释放连接。这时B发出的连接释放报文段必须使FIN = 1。假定B的序号seq = w(在半关闭状态B可能还发送了一些数据)。B还必须重复确认上次发送过的确认号ack = u + 1。这时B进入LAST-ACK(最后确认)状态,等待A的确认。
  • A收到来自B的连接释放报文后,必须对此发出确认。在确认报文段中设置ACK = 1,确认号ack = w + 1,而自己的序号为seq = u + 1(根据TCP标准,前面发送过的FIN报文段要消耗一个序号)。然后进入TIME-WAIT(时间等待)状态。请注意,现在TCP连接还没有释放掉,必须经过时间等待计数器设置的时间2MSL(MSL,Maximum Segment Lifetime,叫做最长报文段寿命,RFC793建议设置为2分钟.)后因此,从A进入到TIME-WAIT后,要经过4分钟才能进入CLOSE状态,才能开始建立下一个新的连接。
  • B接收到来自A的确认报文段,进入CLOSE状态。

疑问

  • 为什么A在TIME-WAIT状态必须等待2MSL的时间?
    1. 为了保证A发送的最后一个ACK报文段能够到达B。这个ACK报文段极有可能丢失,因而使得处在LAST-ACK状态的B收不到确认。B会超时重传FIN+ACK报文段,而A就能在2MSL时间内收到这个重传报文。接着A重传一次确认,重新启动2MSL计时器。最后A和B都能正常进入到CLOSED状态。相反滴,如果A在TIME-WAIT不等待一段时间,而是发送完ACK报文段后就立即释放连接进入CLOSED状态,那么就无法收到B重传的FIN+ACK报文段,因而也不会再发送一次确认报文段。这样,B就无法释放连接了。
    2. 防止”已失效的连接请求报文段”出现在本连接中。经过时间2MSL,就可以使本连接的时间所产生的所有报文段从网络中消失,这样就可以使下一个新的连接中不会出现旧的连接请求报文段。

参考文档