当前位置: 首页 > 知识库问答 >
问题:

为什么许多库没有检测到死的TCP连接?

帅雅逸
2023-03-14

TCP有一个keep-alive机制来检测死连接,但让我吃惊的是,默认情况下这个选项是关闭的,而且很多库/工具都没有利用这个特性。

如果我没有理解错,如果来自对等方的所有FIN/RST数据包丢失,在recv调用中阻塞的TCP连接将无法检测到对等方是否实际中止了连接。

客户端的timeout参数可能会缓解问题,但许多库也没有设置timeout的选项。一个例子是mysql-python连接器没有recv超时选项。再比如,Nginx服务器用proxy_pass与gunicorn后端对话,gunicorn工作人员可能会因为其上的连接死掉而停止响应,但gunicorn工作人员没有办法检测到。

共有1个答案

史磊
2023-03-14

“死连接”一词有点模棱两可--它可能意味着以下任何一种:

>

  • 对等程序关闭其套接字(或者对等程序退出或崩溃,对等计算机的html" target="_blank">操作系统关闭套接字,作为其标准进程清理的一部分)

    与对等计算机的连接突然丢失(这可能是因为对等计算机断电,或者有人拔掉了将对等计算机连接到路由器的以太网线,或者对等计算机的ISP出现路由器故障,或者您的ISP出现路由器故障,等等)

    您的程序和远程对等端之间的数据包路径仍然存在,但该路径上的某些东西丢弃了如此多的数据包,以至于TCP连接的有效传输速率已下降到大约为零。

    那么首先要回答的问题是,TCP层会自行检测上述哪种情况?

    条件(1)是很简单的情况--对等方的TCP堆栈将向您发送FIN数据包,当您的程序的网络堆栈接收到这些数据包时,它将确定TCP连接已关闭并相应地执行操作,因此您的recv()调用将很快返回0。

    在条件(2)中,答案是“有时”--特别是,如果您的程序在套接字的输出缓冲区中有任何TCP数据,它试图发送给对等体,但它从未获得任何关于该数据的ACK包,那么在一定数量的超时(和随后的包重发尝试)之后,您的计算机的TCP堆栈将放弃,宣布连接已死,并单方面关闭TCP连接;此时recv()将返回0。另一方面,如果没有试图发送的传出TCP数据包,则本地TCP堆栈将不会等待任何ACK返回,因此它不会在没有得到ACK时超时,因此它永远不会放弃并关闭TCP连接。在这种情况下,您的recv()调用很可能无限期地阻塞,因为TCP连接是空闲的,并且TCP堆栈无法知道对等体已消失(而不是立即发送任何数据)。SO_KEEPALIVE选项就是要处理这种情况,但由于SO_KEEPALIVE选项的设计者想要在默认情况下节省带宽,而发送自动keepalive数据包会占用额外的带宽,因此他们决定默认情况下禁用keepalive选项。而且,默认的send-a-keepalive间隔按照现代标准通常相当长(例如小时),并且在某些操作系统上很难更改,除非在系统范围内更改,这使得SO_KEEPALIVE对于许多应用程序的作用有限。

    对于条件(3)和(4),TCP连接并不是真的“死”,只是某个设备(对等程序或您的程序和对等程序之间的某个网络设备)不合作。由于TCP层无法知道正在使用它的应用程序试图实现什么,因此它明智地不会尝试在这方面对它们进行猜测,并且它将TCP连接保持打开状态,除非您明确地告诉它关闭()连接。

    既然我们已经描述了TCP层的行为,那么使用它的应用程序和API又如何呢?例如,为什么他们不尝试通过提供更好的检测来改进基本的TCP堆栈行为呢?答案是,他们中的一些人是这样做的;例如,通过周期性地通过任何套接字发送假的“ping”消息(否则会空闲),简单地“刺激”TCP堆栈检测何时没有ACK返回,如上面关于条件(2)的段落中所述。有些甚至更进一步,期望远程对等端发送相应的“pong”消息,以便在(如此多)秒内返回到相同的套接字上,如果没有,程序将单方面关闭套接字。这种方法是可行的,但它也对网络的性能做出了假设,当对等体通过缓慢或不可靠的网络连接时,这可能会导致误报,从而导致不必要的断开连接,这就是为什么许多应用程序/库不实现这种方法(或至少在默认情况下不启用这种方法)。

  •  类似资料:
    • 如何检测TCP连接中的死链?当有人拉网线、关掉网络接口、WiFi翻转或者就像我的情况一样,会出现死链...拔下电源插头。 Keep-alive仅适用于客户端,而不适用于服务器。 update2:现在已删除X64/x86的源代码 补充:我以为我可以通过epoll事件捕获错误。 但如果发生错误,是否需要询问套接字? 我需要心跳来保持TCP连接打开吗? http://tldp.org/howto/tcp

    • 我正在用jackson jr作为jackson databind的轻量级替代品进行实验。我的目标是解析JSON字符串,如果遇到重复的键,则让解析器失败。据我所知,库可能会引发以下异常: 作为比较,如果我尝试使用jackson-data ind进行类似的操作,我会得到预期的IOException: 我能发现的唯一区别是使用了和。但是,我仍然希望在这两种情况下都会引发异常。我错过了什么还是这只是一个错

    • 我试图使用Akka和Scala编写一个TCP服务器,它将实例化参与者,并在客户端分别连接和断开连接时停止参与者。我有一个TCP绑定执行器, 上面实例化上的TCP侦听器,并将处理程序参与者注册到每个连接。 我没有在附近配置的非Windows机器上进行测试,因为我认为这与我在Windows上运行有关,因为在搜索之后,我发现了一个仍然打开的bug--https://github.com/akka/akk

    • 是我在复制时做错了什么,还是有办法不缓存特定的步骤?

    • 问题内容: 如您所见,我在数据库连接上遇到问题。它给了我这个错误: …由于许多连接错误而被阻止 我搜索了一些答案,但无法解决问题。 我不知道我是否提供了您需要的所有信息,所以如果您需要其他信息,请告诉我。我有来自不同计算机的数据库连接,并且创建了一个用户来访问该数据库,但该用户位于主机行中,因此我想使用IP地址更改它以解决安全问题,因此出现了此错误,因此我卡住。 问题答案: MySQL会阻止连接时

    • 本文向大家介绍谈一下,为什么tcp为什么要建立连接?相关面试题,主要包含被问及谈一下,为什么tcp为什么要建立连接?时的应答技巧和注意事项,需要的朋友参考一下 考察点:TCP   保证可靠传输。