请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册
搜索

生活常识字节一面:服务端挂了,客户端的 TCP 连接还在吗


如果「服务端挂掉」指的是「服务端进程崩溃」,那么这个读者猜的想法是对的,服务端的进程在发生崩溃的时候,内核会发送FIN报文,与客户端进行四次挥手。大家好,我是小林。子域名查询的相关问题可以到网站了解下,我们是业内领域专业的平台,您如果有需要可以咨询,相信可以帮到您,值得您的信赖!https://www.ip133.com/


收到一位读者的私信,说字节面试有这么一个问题:服务端挂了,客户端的TCP连接会发生什么



如果「服务端挂掉」指的是「

但是,如果「服务端挂掉」指的是「

如果客户端会发送数据,由于服务端已经不存在,客户端的数据报文会超时重传,当重传次数达到一定阈值后,会断开TCP连接;如果客户端一直不会发送数据,再看客户端有没有开启TCP机制如果有开启,客户端在一段时间后,检测到服务端的TCP连接已经不存在,则会断开自身的TCP连接;

如果没有开启,客户端的TCP连接会一直存在,并不会断开。

上面属于精简回答了,下面我们详细聊聊。

服务端进程崩溃,客户端会发生什么TCP的连接信息是由内核维护的,所以当服务端的进程崩溃后,内核需要回收该进程的所有TCP连接资源,于是内核会发送首次挥手FIN报文,后续的挥手过程也都是在内核完成,并不需要进程的参与,所以即使服务端的进程退出了,还是能与客户端完成TCP四次挥手的过程。

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

服务端主机宕机后,客户端会发生什么当服务端的主机突然断电了,这种情况就是属于服务端主机宕机了。

当服务端的主机发生了宕机,是没办法和客户端进行四次挥手的,所以在服务端主机发生宕机的那一时刻,客户端是没办法立刻感知到服务端主机宕机了,只能在后续的数据交互中来感知服务端的连接已经不存在了。

因此,我们要分两种情况来讨论:

服务端主机宕机后,客户端会发送数据;服务端主机宕机后,客户端一直不会发送数据;服务端主机宕机后,如果客户端会发送数据

在服务端主机宕机后,客户端发送了数据报文,由于得不到响应,在等待一定时长后,客户端就会触发超时重传机制,重传未得到响应的数据报文。

当重传次数达到达到一定阈值后,内核就会判定出该TCP连接有问题,然后通过S接口告诉应用程序该TCP连接出问题了,于是客户端的TCP连接就会断开。

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



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



这个内核参数是控制,在TCP连接建立的情况下,超时重传的比较大次数。

不过_2设置了15次,并不代表TCP超时重传了15次才会通知应用程序终止该TCP连接,内核会根据_2设置的值,计算出一个(如果_2=15,那么计算得到的=924600),如果重传间隔超过这个,则认为超过了阈值,就会停止重传,然后就会断开TCP连接。

在发生超时重传的过程中,每一轮的超时时间(RTO)都是倍数增长的,比如如果首轮RTO是200毫秒,那么第二轮RTO是400毫秒,第轮RTO是800毫秒,以此类推。

而RTO是基于RTT(一个包的往返时间)来计算的,如果RTT较大,那么计算出来的RTO就越大,那么经过几轮重传后,很就达到了上面的值了。

举个例子,如果_2=15,那么计算得到的=924600,如果重传总间隔时长达到了就会停止重传,然后就会断开TCP连接:

如果RTT比较小,那么RTO初始值就约等于下限200,也就是首轮的超时时间是200毫秒,由于总时长是924600,表现出来的现象刚好就是重传了15次,超过了值,从而断开TCP连接如果RTT比较大,假设RTO初始值计算得到的是1000,也就是首轮的超时时间是1秒,那么根本不需要重传15次,重传总间隔就会超过924600。比较小RTO和比较大RTO是在L内核中定义好了:

#TCP_RTO_MAX(()(120*HZ))#TCP_RTO_MIN(()(HZ5))L26+使用1000毫秒的HZ,因此TCP_RTO_MIN?约为200毫秒,TCP_RTO_MAX约为120秒。

如果_?设置为15,且RTT比较小,那么RTO初始值就约等于下限200,这意味着它需要9246秒才能将断开的TCP连接通知给上层(即应用程序),每一轮的RTO增长关系如下表格:



服务端主机宕机后,如果客户端一直不发数据

在服务端主机发送宕机后,如果客户端一直不发送数据,那么还得看是否开启了TCP机制(TCP保活机制)。

如果没有开启TCP机制,在服务端主机发送宕机后,如果客户端一直不发送数据,那么客户端的TCP连接将一直保持存在,所以我们可以得知一个点,在没有使用TCP保活机制,且双方不传输数据的情况下,一方的TCP连接处在ESTABLISHED状态时,并不代表另一方的TCP连接还一定是正常的。

而如果开启了TCP机制,在服务端主机发送宕机后,即使客户端一直不发送数据,在持续一段时间后,TCP就会发送探测报文,探测服务端是否存活:

如果对端是正常工作的。当TCP保活的探测报文发送给对端,对端会正常响应,这样TCP保活时间会被重置,等待下一个TCP保活时间的到来。如果对端主机崩溃,或对端由于其他原因导致报文不可达。当TCP保活的探测报文发送给对端后,石沉大海,没有响应,连续几次,达到保活探测次数后,TCP会报告该TCP连接已经死亡。所以,TCP机制可以在双方没有数据交互的情况,通过探测报文,来确定对方的TCP连接是否存活。



TCP机制具体是怎么样的



TCP机制机制的原理是这样的:

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

在L内核可以有对应的参数可以设置保活时间、保活探测的次数、保活探测的时间间隔,以下都为默认值:

4__=72022__=754__=9每个参数的意思,具体如下:

__=7200:表示保活时间是7200秒(2小时),也就2小时内如果没有任何连接相关的活动,则会启动保活机制__=75:表示每次检测间隔75秒;__=9:表示检测9次响应,认为对方是不可达的,从而中断本次的连接。也就是说在L系统中,比较少需要经过2小时11分15秒才可以发现一个「死亡」连接。



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

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



对的,是有点长。

TCP是TCP层(内核态)现的,它是给所有基于TCP传输协议的程序一个兜底的方案。

际上,我们应用层可以自己现一套探测机制,可以在较短的时间内,探测到对方是否存活。

比如,服务软件一般都会提供_参数,用来指定HTTP长连接的超时时间。如果设置了HTTP长连接的超时时间是60秒,服务软件就会启动一个定时器,如果客户端在完后一个HTTP请求后,在60秒内都没有再发起新的请求,定时器的时间一到,就会触发回调函数来释放该连接。



总结如果「服务端挂掉」指的是「服务端进程崩溃」,服务端的进程在发生崩溃的时候,内核会发送FIN报文,与客户端进行四次挥手。

但是,如果「服务端挂掉」指的是「服务端主机宕机」,那么是不会发生四次挥手的,具体后续会发生什么还要看客户端会不会发送数据

如果客户端会发送数据,由于服务端已经不存在,客户端的数据报文会超时重传,当重传总间隔时长达到一定阈值(内核会根据_2设置的值计算出一个阈值)后,会断开TCP连接;如果客户端一直不会发送数据,再看客户端有没有开启TCP机制如果有开启,客户端在一段时间没有进行数据交互时,会触发TCP机制,探测对方是否存在,如果探测到对方已经消亡,则会断开自身的TCP连接;

如果没有开启,客户端的TCP连接会一直存在,并且一直保持在ESTABLISHED状态。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册