TCP四次揮手中如果服務端沒收到第四次揮手請求,服務端會一直等待嗎?

2022.08.17
TCP四次揮手中如果服務端沒收到第四次揮手請求,服務端會一直等待嗎?

TCP四次揮手中如果服務端沒收到第四次揮手請求,服務端會一直等待嗎?結論是服務端不會一直等待第四次揮手。

搬運一個在某乎的回答,水一篇文章吧。

圖片圖片

TCP四次揮手

正常情況下。只要數據傳輸完了,不管是客戶端還是服務端,都可以主動發起四次揮手,釋放連接。

就跟上圖畫的一樣,假設,這次四次揮手是由客戶端主動發起的,那它就是主動方。服務器是被動接收客戶端的揮手請求的,叫被動方。

客戶端和服務器,一開始,都是處於ESTABLISHED狀態。

  • 第一次挥手:一般情况下,主动方执行close()​或 shutdown()​方法,会发个FIN报文出来,表示"我不再发送数据了"。
  • 第二次挥手:在收到主动方的FIN​报文后,被动方立马回应一个ACK,意思是"我收到你的FIN了,也知道你不再发数据了"。

上面提到的是主动方不再发送数据了。但如果这时候,被动方还有数据要发,那就继续发。注意,虽然第二次和第三次挥手之间,被动方是能发数据到主动方的,但主动方能不能正常收就不一定了,这个待会说。

  • 第三次挥手:在被动方在感知到第二次挥手之后,会做了一系列的收尾工作,最后也调用一个 close()​, 这时候就会发出第三次挥手的 FIN-ACK。
  • 第四次挥手:主动方回一个ACK,意思是收到了。

其中第一次挥手和第三次挥手,都是我们在应用程序中主动触发的(比如调用close()方法),也就是我们平时写代码需要关注的地方。

第二和第四次挥手,都是内核协议栈自动帮我们完成的,我们写代码的时候碰不到这地方,因此也不需要太关心。

另外不管是主动还是被动,每方发出了一个 FIN​ 和一个ACK​ 。也收到了一个 FIN​ 和一个ACK 。

回到题主的问题。

TCP四次挥手中如果服务端没收到第四次挥手请求,服务端会一直等待吗?

第四次挥手是第三次挥手触发的。如果第四次挥手服务端一直没收到,那服务端会认为是不是自己的第三次挥手丢了,于是服务端不断重试发第三次挥手(FIN).重发次数由系统的tcp_orphan_retries参数控制。重试多次还没成功,服务端直接断开链接。所以结论是服务端不会一直等待第四次挥手。

圖片

TCP第四次挥手丢失

# cat /proc/sys/net/ipv4/tcp_orphan_retries
0
  • 1.
  • 2.

另外,你会发现tcp_orphan_retries参数是0,但其实并不是不重试的意思。为0时,默认值为8. 也就是重试8次。

/* Calculate maximal number or retries on an orphaned socket. */
static int tcp_orphan_retries(struct sock *sk, int alive)
{
    int retries = sysctl_tcp_orphan_retries; /* May be zero. */

    /* We know from an ICMP that something is wrong. */
    if (sk->sk_err_soft && !alive)
        retries = 0;

    /* However, if socket sent something recently, select some safe
     * number of retries. 8 corresponds to >100 seconds with minimal
     * RTO of 200msec. */
    if (retries == 0 && alive)
        retries = 8;
    return retries;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.

当然如果服务端重试发第三次挥手FIN的过程中,还是同样的端口和IP,起了个新的客户端,这时候服务端重试的FIN被收到后,客户端就会认为是不正常的数据包,直接发个RST给服务端,这时候两端连接也会断开。