0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

TCP keepalive机制具体是怎么样的

程序人生 来源:小林coding 作者:小林coding 2022-03-11 16:50 次阅读

大家好,我是小林。

今天,聊一个有趣的问题:拔掉网线几秒,再插回去,原本的 TCP 连接还存在吗?

可能有的同学会说,网线都被拔掉了,那说明物理层被断开了,那在上层的传输层理应也会断开,所以原本的 TCP 连接就不会存在的了。就好像, 我们拨打有线电话的时候,如果某一方的电话线被拔了,那么本次通话就彻底断了。

真的是这样吗?

上面这个逻辑就有问题。问题在于,错误的认为拔掉网线这个动作会影响传输层,事实上并不会影响。

实际上,TCP 连接在 Linux 内核中是一个名为 struct socket 的结构体,该结构体的内容包含 TCP 连接的状态等信息。当拔掉网线的时候,操作系统并不会变更该结构体的任何内容,所以 TCP 连接的状态也不会发生改变。

我在我的电脑上做了个小实验,我用 ssh 终端连接了我的云服务器,然后我通过断开 wifi 的方式来模拟拔掉网线的场景,此时查看 TCP 连接的状态没有发生变化,还是处于 ESTABLISHED 状态。

9bddba90-a020-11ec-952b-dac502259ad0.png

通过上面这个实验结果,我们知道了,拔掉网线这个动作并不会影响 TCP 连接的状态。接下来,要看拔掉网线后,双方做了什么动作。所以,针对这个问题,要分场景来讨论:

拔掉网线后,有数据传输;

拔掉网线后,没有数据传输;

拔掉网线后,有数据传输

在客户端拔掉网线后,服务端向客户端发送的数据报文会得不到任何的响应,在等待一定时长后,服务端就会触发超时重传机制,重传未得到响应的数据报文。如果在服务端重传报文的过程中,客户端刚好把网线插回去了,由于拔掉网线并不会改变客户端的 TCP 连接状态,并且还是处于 ESTABLISHED 状态,所以这时客户端是可以正常接收服务端发来的数据报文的,然后客户端就会回 ACK 响应报文。此时,客户端和服务端的 TCP 连接依然存在的,就感觉什么事情都没有发生。但是,如果如果在服务端重传报文的过程中,客户端一直没有将网线插回去,服务端超时重传报文的次数达到一定阈值后,内核就会判定出该 TCP 有问题,然后通过 Socket 接口告诉应用程序该 TCP 连接出问题了,于是服务端的 TCP 连接就会断开。而等客户端插回网线后,如果客户端向服务端发送了数据,由于服务端已经没有与客户端相同四元祖的 TCP 连接了,因此服务端内核就会回复 RST 报文,客户端收到后就会释放该 TCP 连接。此时,客户端和服务端的 TCP 连接都已经断开了。

那 TCP 的数据报文具体重传几次呢?

在 Linux 系统中,提供了一个叫 tcp_retries2 配置项,默认值是 15,如下图:

9c0bee2e-a020-11ec-952b-dac502259ad0.png

这个内核参数是控制,在 TCP 连接建立的情况下,超时重传的最大次数。不过 tcp_retries2 设置了 15 次,并不代表 TCP 超时重传了 15 次才会通知应用程序终止该 TCP 连接,内核还会基于「最大超时时间」来判定。

每一轮的超时时间都是倍数增长的,比如第一次触发超时重传是在 2s 后,第二次则是在 4s 后,第三次则是 8s 后,以此类推。

9c1edde0-a020-11ec-952b-dac502259ad0.png

内核会根据 tcp_retries2 设置的值,计算出一个最大超时时间。

在重传报文且一直没有收到对方响应的情况时,先达到「最大重传次数」或者「最大超时时间」这两个的其中一个条件后,就会停止重传,然后就会断开 TCP 连接。

拔掉网线后,没有数据传输

针对拔掉网线后,没有数据传输的场景,还得看是否开启了 TCP keepalive 机制 (TCP 保活机制)。如果没有开启 TCP keepalive 机制,在客户端拔掉网线后,并且双方都没有进行数据传输,那么客户端和服务端的 TCP 连接将会一直保持存在。而如果开启了 TCP keepalive 机制,在客户端拔掉网线后,即使双方都没有进行数据传输,在持续一段时间后,TCP 就会发送探测报文:

如果对端是正常工作的。当 TCP 保活的探测报文发送给对端, 对端会正常响应,这样 TCP 保活时间会被重置,等待下一个 TCP 保活时间的到来。

如果对端主机崩溃,或对端由于其他原因导致报文不可达。当 TCP 保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,TCP 会报告该 TCP 连接已经死亡。

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

TCP keepalive 机制具体是怎么样的?

这个机制的原理是这样的:定义一个时间段,在这个时间段内,如果没有任何连接相关的活动,TCP 保活机制会开始作用,每隔一个时间间隔,发送一个探测报文,该探测报文包含的数据非常少,如果连续几个探测报文都没有得到响应,则认为当前的 TCP 连接已经死亡,系统内核将错误信息通知给上层应用程序。在 Linux 内核可以有对应的参数可以设置保活时间、保活探测的次数、保活探测的时间间隔,以下都为默认值:

net.ipv4.tcp_keepalive_time=7200

net.ipv4.tcp_keepalive_intvl=75

net.ipv4.tcp_keepalive_probes=9

tcp_keepalive_time=7200:表示保活时间是 7200 秒(2小时),也就 2 小时内如果没有任何连接相关的活动,则会启动保活机制;

tcp_keepalive_intvl=75:表示每次检测间隔 75 秒;

tcp_keepalive_probes=9:表示检测 9 次无响应,认为对方是不可达的,从而中断本次的连接。

也就是说在 Linux 系统中,最少需要经过 2 小时 11 分 15 秒才可以发现一个「死亡」连接。

9c458c24-a020-11ec-952b-dac502259ad0.png

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

TCP keepalive 机制探测的时间也太长了吧?

对的,是有点长。TCP keepalive 是 TCP 层(内核态) 实现的,它是给所有基于 TCP 传输协议的程序一个兜底的方案。实际上,我们应用层可以自己实现一套探测机制,可以在较短的时间内,探测到对方是否存活。比如,web 服务软件一般都会提供 keepalive_timeout 参数,用来指定 HTTP 长连接的超时时间。如果设置了 HTTP 长连接的超时时间是 60 秒,web 服务软件就会启动一个定时器,如果客户端在完后一个 HTTP 请求后,在 60 秒内都没有再发起新的请求,定时器的时间一到,就会触发回调函数来释放该连接。

9c5736d6-a020-11ec-952b-dac502259ad0.png

总结

客户端拔掉网线后,并不会直接影响 TCP 连接状态。所以,拔掉网线后,TCP 连接是否还会存在,关键要看拔掉网线之后,有没有进行数据传输。有数据传输的情况:

在客户端拔掉网线后,如果服务端发送了数据报文,那么在服务端重传次数没有达到最大值之前,客户端就插回了网线,那么双方原本的 TCP 连接还是能正常存在,就好像什么事情都没有发生。

在客户端拔掉网线后,如果服务端发送了数据报文,在客户端插回网线之前,服务端重传次数达到了最大值时,服务端就会断开 TCP 连接。等到客户端插回网线后,向服务端发送了数据,因为服务端已经断开了与客户端相同四元组的 TCP 连接,所以就会回 RST 报文,客户端收到后就会断开 TCP 连接。至此, 双方的 TCP 连接都断开了。

没有数据传输的情况:

如果双方都没有开启 TCP keepalive 机制,那么在客户端拔掉网线后,如果客户端一直不插回网线,那么客户端和服务端的 TCP 连接状态将会一直保持存在。

如果双方都开启了 TCP keepalive 机制,那么在客户端拔掉网线后,如果客户端一直不插回网线,TCP keepalive 机制会探测到对方的 TCP 连接没有存活,于是就会断开 TCP 连接。而如果在 TCP 探测期间,客户端插回了网线,那么双方原本的 TCP 连接还是能正常存在。

除了客户端拔掉网线的场景,还有客户端「宕机和杀死进程」的两种场景。第一个场景,客户端宕机这件事跟拔掉网线是一样无法被服务端的感知的,所以如果在没有数据传输,并且没有开启 TCP keepalive 机制时,服务端的 TCP 连接将会一直处于 ESTABLISHED 连接状态,直到服务端重启进程。所以,我们可以得知一个点。在没有使用 TCP 保活机制,且双方不传输数据的情况下,一方的 TCP 连接处在 ESTABLISHED 状态时,并不代表另一方的 TCP 连接还一定是正常的。第二个场景,杀死客户端的进程后,客户端的内核就会向服务端发送 FIN 报文,与客户端进行四次挥手。所以,即使没有开启 TCP keepalive,且双方也没有数据交互的情况下,如果其中一方的进程发生了崩溃,这个过程操作系统是可以感知的到的,于是就会发送 FIN 报文给对方,然后与对方进行 TCP 四次挥手。

原文标题:拔掉网线后, 原本的 TCP 连接还存在吗?

文章出处:【微信公众号:程序人生】欢迎添加关注!文章转载请注明出处。

审核编辑:彭菁
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 服务器
    +关注

    关注

    12

    文章

    8954

    浏览量

    85069
  • TCP
    TCP
    +关注

    关注

    8

    文章

    1347

    浏览量

    78925
  • WIFI
    +关注

    关注

    81

    文章

    5279

    浏览量

    203050

原文标题:拔掉网线后, 原本的 TCP 连接还存在吗?

文章出处:【微信号:coder_life,微信公众号:程序人生】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    MODBUS TCP 转 CANOpen

    产品概述 SG-TCP-COE-210 网关可以实现将 CANOpen 接口设备连接到 MODBUS TCP 网络中。用户不需要了解具体的 CANOpen 和 Modbus TCP
    的头像 发表于 09-24 13:59 206次阅读
    MODBUS <b class='flag-5'>TCP</b> 转 CANOpen

    EtherCAT从站转Modbus TCP协议网关(YC-ECT-TCP

    怎样实现EtherCAT网络与Modbus TCP网络的连接互通?不少朋友在这个问题上存在疑惑。接下来,将为大家集中解惑。实际上,远创智控YC-ECT-TCP这一设备能够有效地处理此难题。下面,作者为大家详细介绍该设备的功能、参数以及
    的头像 发表于 08-20 20:07 415次阅读
    EtherCAT从站转Modbus <b class='flag-5'>TCP</b>协议网关(YC-ECT-<b class='flag-5'>TCP</b>)

    简述TCP协议的三次握手机制

    TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。它主要用于在IP网络中进行数据传输。TCP协议的三次握手机制
    的头像 发表于 08-16 10:57 490次阅读

    Modbus(TCP)转Profinet从总线协议转换网关(JM-TCP-PN)

    大家详尽阐述该设备的功能、参数以及具体的配置方式。 一,产品主要功能 1、捷米特JM-TCP-PN该网关的核心功能是将Profinet协议转换为Modbus TCP协议,使得Profinet设备能够
    的头像 发表于 08-16 10:14 285次阅读
    Modbus(<b class='flag-5'>TCP</b>)转Profinet从总线协议转换网关(JM-<b class='flag-5'>TCP</b>-PN)

    求助,关于AT+CIPSTART指令keepalive功能的问题求解

    都没有任何响应,所以也不知道具体是多久断开。 所以尝试用AT+CIPSTART指令设置Keepalive功能来保持服务器连接,结果发现我设置成60秒,到了60秒就返回一个CLOSE。 一开始我以为是
    发表于 07-16 07:47

    如何使用espconn_set_keepalive

    我想建立一个 TCP 连接,该连接在第一次数据发送后不会关闭,我阅读了有关 espconn_set_保持活着 函数的信息,该函数将心跳发送到服务器,因此它不会断开连接(如果我理解正确的话)。但是我
    发表于 07-12 15:10

    使用esp_iot_sdk_v1.0.1_15_04_24时keepalive无效的原因?

    我的keepalive功能一直都正常,替换成新的esp_iot_sdk_v1.0.1_15_04_24 SDK后,keepalive就没有了,我的代码未变动 nKeepaliveParam
    发表于 07-12 09:28

    请问ESP8266 SDK可以添加KeepAlive获取状态接口吗?

    我在我的 TCP 套接字中启用了 keepalive,它可以发送和接收 keepalive packt 将本地服务器,但我突然关闭了我的本地服务器以测试 esp8266 在这种情况下可以注意到
    发表于 07-12 09:03

    ESP8266 TCP保持活动状态功能似乎不起作用,为什么?

    。 当我为TCP客户端设置保持活动状态参数时: ... client_fd= socket(); ... int keepAlive = 1; //enable keepalive int
    发表于 07-12 08:00

    ESP32-S3使用tcp_server例程,将网络数据和串口数据透传延迟过高怎么解决?

    ;, errno);break;}tcp_sock = sock;// Set tcp keepalive optionsetsockopt(sock, SOL_SOCKET, SO_KEEP
    发表于 06-06 06:06

    TCP协议中的拥塞控制机制与网络稳定性

    TCP协议中的拥塞控制机制与网络稳定性的深度探讨 随着互联网的快速发展,网络流量呈现爆炸式增长,网络拥塞问题逐渐凸显。为了维护网络的稳定运行,TCP协议中引入了拥塞控制机制。这一
    的头像 发表于 04-19 16:42 355次阅读

    UDP与TCP的主要区别 UDP能否像TCP实现可靠传输?

    UDP与TCP的主要区别 UDP能否像TCP实现可靠传输?TCP如何实现可靠性传输? UDP和TCP是两种常用的传输层协议,它们之间的主
    的头像 发表于 01-22 16:10 727次阅读

    如何选择传输层协议?TCP和UDP的优缺点和适用场合

    和可靠性至关重要。本文将详细介绍TCP和UDP的优缺点以及适用场合。 1. TCP的优点和适用场合: TCP是一种可靠的、面向连接的传输层协议,它提供了重发机制、数据丢失检测和拥塞控制
    的头像 发表于 12-11 11:42 922次阅读

    TCP 协议的运作机制

    今天我们将 从稳定性角度深挖 TCP 协议的运作机制 。 如今,大半个互联网都建立在 TCP 协议之上,我们使用的 HTTP 协议、消息队列、存储、缓存,都需要用到 TCP 协议——
    的头像 发表于 11-13 11:34 542次阅读
    <b class='flag-5'>TCP</b> 协议的运作<b class='flag-5'>机制</b>

    为什么要使用 TCP keepalive

    为了理解 TCP keepalive的作用。我们需要清楚,当TCP的Peer A ,Peer B 两端建立了连接之后,如果一端突然拔掉网线或拔掉电源时,怎么检测到拔掉网线或者拔掉电源、链路不通
    的头像 发表于 11-13 11:28 495次阅读
    为什么要使用 <b class='flag-5'>TCP</b> <b class='flag-5'>keepalive</b>