tcp异常连接的检测方法

myonlybook myonlybook     2022-12-28     199

关键词:

背景

  在平时的开发中,经常会碰到一些需要检测tcp连接是否正常的场景。比如一个分布式的应用,一个调度任务的节点管理一堆用来跑业务的节点。当调度节点进行调度的时候,需要把任务分发给它认为正常的业务节点去执行。业务节点是否正常,一个重要的参考依据就是调度节点和业务节点之间的tcp连接是否正常。这时候就需要调度节点主动地去检测tcp连接。常见的检测方法有以下几种

 

方案一、通过TCP协议的返回值进行判断

    <1> 利用select,把socket设置为非阻塞。然后使用select等待该socket的可读事件。如果socket可读,但是recv的返回值是0,则说明socket已经被对端断开,这时候就可以调用close关闭socket。这里还要注意一点,recv还可能返回负数,这个代表socket操作出错。但是仍然应该判断一下errno是否为EINTR。如果errno是EINTR,则说明recv函数是被信号中断返回的,这时候不能判断socket的连接是否正常,也不应该调用close关闭socket。

    <2> 利用poll的事件。poll本身提供了POLLHUP,POLLERR,  POLLNVAL三个事件。如果文件描述符是socket,则POLLHUP代表socket已经断开了连接,在TCP底层就是已经收到了FIN报文。POLLERR表示socket出现了错误,一般情况下是收到了rst报文,或者已经发送了rst报文。这两种情况都应该调用close关闭socket。POLLNVAL代表socket没有打开,这时不能使用close关闭它,而应该根据自己的业务做一些其他的操作。因为关闭一个未打开的socket会出错。

    这两种方法都可以很精确地判断tcp连接是否正常,但是仍然有很明显的缺陷。就是它只可以根据TCP操作的返回值来进行判断。如果TCP四次握手没有正常被执行呢?比如连接对端机器直接挂了,那么就不会发送FIN报文给这一端,select不会返回socket可读,poll不会返回socket异常。那么这个死链接将会永远检测不到。直到写这个socket的时候,对端直接返回一个ret报文,这时才知道这个连接已经断掉了。这就意味着tcp连接异常可能永远检测不到,或者检测到的延迟非常大。这对于一些资源宝贵而且要求高性能的服务器是不能接受的,比如游戏服务器,比如搜索服务器。

  

方案二、在第一种方案的基础上设置socket的 keep alive 机制

    方案一的主要缺陷在于检测不及时,或者根本检测不到。TCP协议提供了keep alive机制。如果开启了这个特性(暂时称开启了keep alive的一端为开启端),在默认情况下,开启的着一端的socket相关结构中会维护一个定时器,默认是2小时。如果在2小时内两端没有数据往来,那么开启端就会给另一端发送一个ack空报文。这时候分几种情况:

    <1> 对端机器可达,而且TCP相关组件运行正常。那么对端就会给开启端发送一个ack空报文。这时开启端就知道对端是正常的,意味着tcp连接也没有问题。开启端会重新初始化定时器,等待下一个超时的到来。需要注意的是,如果两端之间有数据往来,定时器也会被重新初始化为2个小时。  

    <2> 对端挂了,或者正在重启,还没有完全起来。或者对端服务器不可达。 这种状态的对端是不会响应这个ack的。开启端的 keep alive 机制会把这种情况当探测超时来处理,并且重新发送ack到对端。当超时次数超过一定限制,keep alive 就认为这个tcp连接有问题。典型值是每次75秒,超时9次。

    <3> 对端挂过,但是已经重启完成。这时候发送这个ack和写已经关闭的socket是一种情况,对端会返回一个rst报文,这样开启端就知道tcp连接出问题了。

    可以看出 keep alive 机制弥补了方案一种不能判断没有进行正常四次挥手连接出现问题的缺陷。默认的发送超时和发送间隔都是可以调整的。    

    tcp_keepalive_time: KeepAlive的空闲时长,默认是2小时

    tcp_keepalive_intvl: KeepAlive探测包的发送间隔,默认是75s 

    tcp_keepalive_probes: 在tcp_keepalive_time之后,没有接收到对方确认,继续发送保活探测包次数,默认是9次

    这3个参数使用 setsockopt函数都是可以配置的。

    方案二看似已经完美了,能够比较精确而且及时地发现有问题的连接。但是还有2个缺点。第一个是 keep alive 机制看似牛逼,但是很多人不建议使用。因为上面说的3个参数很难根据业务场景给出合适的值,设置不好很容易对tcp连接状态发生误判,关闭了一个本来正常的连接。而且没有一个主动通知应用层的方式。比如socket连接出错了,TCP协议接到了rst,fin,或者keep alive判断出socket有问题了,但是并不会主动去通知应用层,必须我们自己 recv socket或者等待错误事件才能得到这个错误。第二个是很多场景下,keep alive 检测仍然不够及时,比如对端挂了,最长需要等待 tcp_keepalive_intvl * tcp_keepalive_probes时间才可以检测出来,而且这两个值还不能设置得太小,太小了容易误判。

 

方案三、应用层的心跳

    这种形式的心跳设计就比较多样化了,而且灵活,可以很好地适应业务场景。唯一的缺点就是要自己写代码。我目前接触到的就是定期进行RPC调用。看RPC调用是否正常,如果返回错误或者抛出异常,就说明连接有问题。

 

 

socket心跳超时检测,快速处理新思路(适用于超大量tcp连接情况下)(代码片段)

假设一种情景:TCP服务器有1万个客户端连接,如果客户端5秒钟不发数据,则要断开。服务端如何检测客户端是否超时?这看起来是一个非常简单的问题,其实不然!最简单的处理方法是:启动一个线程,每隔一段时间,检查每... 查看详情

graphanomalydetectionwithdeeplearning——节点检测

节点检测算法分类ANOSNDonPlainGraphs平面图上的节点异常检测传统的异常检测方法基于网络表示的异常检测方法ANOSNDonAttributedGraphs属性图上的节点异常检测ANOSNDOnDynamicGraphs动态图上的节点异常检测传统非深度检测方法基于网络表示... 查看详情

graphanomalydetectionwithdeeplearning——节点检测

节点检测算法分类ANOSNDonPlainGraphs平面图上的节点异常检测传统的异常检测方法基于网络表示的异常检测方法ANOSNDonAttributedGraphs属性图上的节点异常检测ANOSNDOnDynamicGraphs动态图上的节点异常检测传统非深度检测方法基于网络表示... 查看详情

如何检测和删除扭曲的死tcp连接?(代码片段)

...的Iot套接字服务器。后来我发现设备是否是硬件复位,TCP连接仍然保留在服务器端。我想由于微控制器已经复位,TCP连接没有时间断开连接。由于我只允许一个设备连接一个,如果TCP连接失效,并且服务器没有得到断开连接请求... 查看详情

如何通过 Windows API GetExtendedTCpTable 检测新的 TCP 连接

】如何通过WindowsAPIGetExtendedTCpTable检测新的TCP连接【英文标题】:HowtodetectaNEWTCPConnectionsByWindowsAPIsGetExtendedTCpTable【发布时间】:2011-07-2206:29:44【问题描述】:我已经为本地电脑制作了一个用于查看活动tcp/udp连接的应用程序。现... 查看详情

Linux 中异常缓慢的 TCP 连接

】Linux中异常缓慢的TCP连接【英文标题】:UnusuallyslowTCP-connectioninLinux【发布时间】:2020-05-0314:30:55【问题描述】:我编写了基于Berkeley套接字的用户模式客户端-服务器c应用程序,该套接字通过某些专用网络进行交互。情况肯定... 查看详情

如何使用 Amphp 捕获 php websocket 断开的 TCP 连接异常?

】如何使用Amphp捕获phpwebsocket断开的TCP连接异常?【英文标题】:HowtocatchaphpwebsocketbrokenTCPconnectionexceptionwithAmphp?【发布时间】:2019-11-2618:01:06【问题描述】:这是我在连接仍然存在时正在运行的当前WebSocket循环。但是连续连接11... 查看详情

异常点检测方法

参考技术A一、基本概念异常对象被称作离群点。异常检测也称偏差检测和例外挖掘。常见的异常成因:数据来源于不同的类(异常对象来自于一个与大多数数据对象源(类)不同的源(类)的思想),自然变异,以及数据测量... 查看详情

SQLServer异常;与主机 localhost、端口 1433 的 TCP/IP 连接失败

】SQLServer异常;与主机localhost、端口1433的TCP/IP连接失败【英文标题】:SQLServerException;TheTCP/IPconnectiontothehostlocalhost,port1433hasfailed【发布时间】:2016-08-0920:20:17【问题描述】:使用这个连接字符串jdbc:sqlserver://localhost\\\\SQLEXPRESS:1433... 查看详情

从多个 tcp 连接读取数据

】从多个tcp连接读取数据【英文标题】:Readingdatafrommultipletcpconnection【发布时间】:2017-08-1019:23:56【问题描述】:假设您有200个检测器通过tcp套接字连接到您的程序。他们经常发送他们的数据和我想尽可能高效地处理它。我可以... 查看详情

graphanomalydetectionwithdeeplearning——节点检测

...nwithDeepLearning论文地址:https://arxiv.org/abs/2106.07178前言异常节点的分类异常节点可以进一步分为以下三种类型:全局异常:只考虑节点属性。它们是具有与图中所有其他节点显著不同的属性的节点。结构异常:只考... 查看详情

哪些常见的网络情况会造成tcp同步包与tcp同步确认包异常

参考技术A传输控制协议(TransmissionControlProtocol,TCP)TCP协议主为了在主机间实现高可靠性的包交换传输协议。本文将描述协议标准和实现的一些方法。因为计算机网络在现代社会中已经是不可缺少的了,TCP协议主要在网络不可靠... 查看详情

有没有办法使用 flash.net.Socket 检测 TCP 连接已被拒绝?

】有没有办法使用flash.net.Socket检测TCP连接已被拒绝?【英文标题】:IsthereawaytodetectthatTCPconnectionhasbeenrefusedusingflash.net.Socket?【发布时间】:2011-03-2418:12:42【问题描述】:有一个使用flash.net.Socket连接到服务器的flash电影。但是可... 查看详情

r异常数据检测及处理方法(代码片段)

R异常数据检测及处理方法数据中的异常值可能会影响或者干扰模型的准确性以及可靠性,如果我们不正确地检测和处理它们,尤其是在回归模型中异常值对模型的干扰比较大,即回归模型对异常值敏感。为什么异常点检测很重... 查看详情

netstat备忘清单_开发速查表分享

...等操作系统中使用,它可以帮助用户查看本地主机的网络连接情况。它可以报告出本地主机的TCP/IP协议统计信息,包括活动的TCP连接,UDP端口,所有的接口信息,以及活动的网络连接等。netstat命令可以用来查看本机的网络连接... 查看详情

tcp连接异常:brokenpipe和eof(代码片段)

本文介绍3种TCP连接异常的情况。1.server端没有启动,client尝试连接./clientdialfailed:dialtcp127.0.0.1:8080:connect:connectionrefused通过tcpdump抓包,可以看到当server没有启动的时候,client向server8080端口发送数据后,client端会收到RST。2.client端... 查看详情

怎样检测tcp/udp端口的连通性(代码片段)

...通性TC端口的连通性,一般通过telnet检测:TCP协议是面向连接的,可以直接通过telnet命令连接telnethost-ipport 2UDP端口的连通性因为公司网络防火墙一般对端口会有一些限制,通过公司网络访问外部服务器特定端口时,需要检测... 查看详情

SocketPolicy 异常 int TCP Unity 与 C# 服务器之间的连接

】SocketPolicy异常intTCPUnity与C#服务器之间的连接【英文标题】:SocketPolicyexceptionintTCPConnectionbetweenunityandC#server【发布时间】:2017-05-1308:26:31【问题描述】:我正在开发简单的多人游戏,我正在自己的编码服务器上工作(在C#中)。... 查看详情