关于TCP连接保活问题

首先参考文章:

被鹅厂面怕了:TCP 连接异常的问题 - 知乎 (zhihu.com)

如果两端的 TCP 连接一直没有数据交互,达到了触发 TCP 保活机制的条件(window下2小时没有数据交互),那么内核里的 TCP 协议栈就会发送探测报文。

  • 如果对端程序是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。
  • 如果对端主机崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。

所以,TCP 保活机制可以在双方没有数据交互的情况,通过探测报文,来确定对方的 TCP 连接是否存活。

注意,应用程序若想使用 TCP 保活机制需要通过 socket 接口设置 SO_KEEPALIVE 选项才能够生效,如果没有设置,那么就无法使用 TCP 保活机制。

知道了 TCP keepalive 作用,我们再回过头看题目中的「主机崩溃」这种情况。

在没有开启 TCP keepalive,且双方一直没有数据交互的情况下,如果客户端的「主机崩溃」了,会发生什么。

如果客户端主机崩溃了,服务端是无法感知到的,在加上服务端没有开启 TCP keepalive,又没有数据交互的情况下,服务端的 TCP 连接将会一直处于 ESTABLISHED 连接状态,直到服务端重启进程。

所以,我们可以得知一个点。

在没有使用 TCP 保活机制,且双方不传输数据的情况下,一方的 TCP 连接处在 ESTABLISHED 状态时,并不代表另一方的 TCP 连接还一定是正常的。

那题目中的「进程崩溃」的情况呢?

我自己做了个实验,使用 kill -9 来模拟进程崩溃的情况,发现在 kill 掉进程后,服务端会发送 FIN 报文,与客户端进行四次挥手。

所以,即使没有开启 TCP keepalive,且双方也没有数据交互的情况下,如果其中一方的进程发生了崩溃,这个过程操作系统是可以感知的到的,于是就会发送 FIN 报文给对方,然后与对方进行 TCP 四次挥手。

根据CHATGPT回复:

在TCP连接中,发送的每一个数据段都需要接收方发送确认(ACK)来进行确认,以保证数据的可靠传输。这是TCP协议的核心机制之一。

具体来说,发送方将数据分割成一个个数据段(Segment),并且每一个数据段都包含一个序号(Sequence Number)和一个确认号(Acknowledgement Number)。接收方收到数据段后,会向发送方发送一个确认报文,其中确认号就是发送方发送的数据段中的序号加上数据的长度。发送方收到确认报文后,就知道这个数据段已经被成功接收了,可以继续发送下一个数据段。

需要注意的是,TCP协议中的确认是有选择性的(Selective ACK)。也就是说,接收方不一定要对每一个数据段都发送确认报文,而是可以通过发送一组确认号来表示已经成功接收到一连串的数据段。这样可以减少确认报文的数量,提高数据传输的效率。

总之,在TCP连接中,数据的可靠传输是通过确认机制来保证的,每一个数据段都需要接收方发送确认报文来进行确认。这也是TCP协议能够保证数据传输可靠性的重要机制之一。

 

 

 

 

 

 

 

 

 

 

posted @ 2023-04-15 13:06  叨叨的蜗牛  阅读(283)  评论(0)    收藏  举报