我需要定期发送心跳包以保持TCP连接吗?

110

我有两个组件,它们通过TCP/IP进行通信。组件A充当服务器/监听器,组件B是客户端。这两个组件应该尽快进行通信。任何时候都只能有一个连接(尽管这与本问题无关)。我公司的一位高级开发人员说我需要在两个组件之间使用应用程序级心跳来确保连接保持打开状态。

我认为使用TCP/IP可以使连接保持打开状态,但我读过许多博客和网站,它们都说心跳在这些应用程序之间相当普遍。

我知道A组件向B组件发送心跳的部分原因是,如果B组件存在通信问题(链接已断开或B组件未运行),它可以通知支持部门。还有其他必须要使用心跳吗?例如,确保经常有东西“在管道中”以保持其处于打开状态吗?

组件A目前每20秒向组件B发送心跳,如果120秒内没有收到来自组件B的回复,则关闭连接。然后,在假定组件B将定期尝试重新连接以恢复连接的情况下,它会继续监听连接。这很成功。

再次强调我的问题:是否需要使用心跳来保持TCP/IP连接的活动状态?


1
这种行为也可能与实现有关吗?这是TCP标准中指定的内容,还是留作实现细节?希望其他人也能回答这个问题。 - dss539
1
我会说这是一个实现细节,因为并不是所有基于TCP/IP的协议都实现了这样的功能,这完全取决于你。 - Lloyd
6
是的,你的连接断开并不是因为TCP/IP,而可能是由于其他硬件或软件所经过的路径,比如防火墙和家庭路由器,它们可能会中断非活动状态的TCP连接。相关参考链接:https://dev59.com/5G865IYBdhLWcg3wQMOW#5149662 - markmnl
16个回答

59

连接应该始终保持打开状态,但是通常会看到协议实现心跳以帮助检测死连接,例如 IRC 使用 PING 命令。


42
保持长连接的另一个常见原因是为了穿越NAT网关保持连接开启。虽然TCP本身不需要使用keepalive来运作,但是NAT网关会在一定时间后“断开”TCP连接,因此使用keepalive是很常见的。 - nos
5
正常的超时时间是多少?秒、分钟、小时? - MiniGod
@Lloyd 我“想”MiniGod的意思是,“一个‘正常’的超时时间会有多长?”(以秒、分钟、小时等为单位给出答案) - jeromej
@JeromeJ 谁知道呢,已经过了几年了 ;) - Lloyd
此外,如果您的连接经过代理,如果被视为陈旧,则可以预期连接将断开。我认为在这种情况下保持连接不会有所帮助,因为TCP的这个方面不会传播到应用程序。 - Ghita
显示剩余2条评论

58

正如许多人所指出的那样,如果不做任何处理,TCP连接将保持开启。然而,如果你在连接中间有一个跟踪状态的设备(例如防火墙),你可能需要保持存活以防止状态表目录过期。


TCP连接会一直保持活动状态吗? - user7817808

27

如果您的组件:

  • 在传统有线网络中
  • 它们之间没有防火墙或NAT路由器
  • 它们都不会崩溃

那么您就不需要有心跳。

如果这些假设中有任何一个是错误的(我在看你,GPRS!),那么很快就需要使用心跳。


1
这通常涉及到网络。考虑彼得·德意志的《分布式计算谬论》;我们知道网络本质上是不可靠的,因此应该将其视为应用程序中几乎肯定会出现故障的一个点。在这种情况下,无论是传统有线网络还是其他类型的网络,都应该假设您在某个时刻会遇到故障,并设计您的应用程序以处理这种情况。 - Steven Bakhtiari

13

您不需要自己发送心跳。TCP连接将保持打开状态,无论使用情况如何。

请注意,TCP实现了一个可选的keepalive机制,可以用于及时识别关闭的连接,而无需在以后某个时间发送数据,然后发现连接已关闭。


1
它在Linux上应该如何工作?它实际上可以工作吗?我能否安排超时时间少于2小时?例如30秒? - Itay Levin
为了使其工作,应用程序需要支持keepalive。在Linux中仅启用它是不够的。 - Mike Vella

9

如果您正在使用Windows系统,请注意TCP Keep-alive。默认情况下,除非您通过Windows注册表或setsockopt全局启用它,否则它是禁用的。

默认的Keep-alive间隔为2小时。

http://msdn.microsoft.com/en-us/library/ms819735.aspx

如果不需要2小时的Keep-alive时间,您可能需要实现自己的心跳并在Windows上禁用TCP Keep-alive。


保持连接可以通过套接字选项SO_KEEPALIVE来实现。默认情况下,消息之间的时间间隔为1秒。这可能需要两个端点的支持才能正确运行。 - Pekka

4

TCP/IP连接必须保持心跳吗?

心跳机制有助于检测连接是否已中断。


4

TCP协议将保持连接活动。应用程序心跳是为了应用程序层面的考虑,例如故障转移、负载平衡或向管理员报告潜在问题。


3
心跳是告诉服务器你还活着的好方法。如果服务器使用DoS攻击防护系统,当服务器检测到某个连接在一定时间内没有活动后,它(服务器)可能会取消该特定连接的所有资源分配。
没有要求实施任何心跳机制。

但是,如果您设计的应用程序的主要标准是响应性,那么使用心跳是很好的选择。您不希望浪费时间建立连接、DNS查询和路径发现等操作。只需保持连接始终保持连接状态,保持发送心跳信号,应用程序就知道连接是存活的,并且不需要连接设置。只需简单地发送和接收数据即可。


3
TCP不需要保持活动消息来保持会话开启。该协议旨在用于终端和打印机,它们可以每隔几周进行一次活动而不会出现问题。
其他答案中指出的透明网络级元素确实可能会造成令人难以置信的混乱,甚至在它们失控并且丢失会话或干扰流量时可能导致整个工厂瘫痪。这总是不正确的,不应该需要任何应用程序或操作系统开发者采取行动。
如果没有设置保持活动,通信错误仅会在下一次尝试传输时被检测到。
有三种可能的保持活动级别:
1.使用操作系统设置或SO_KEEPALIVE选项的套接字级保持活动。这是透明的,并且将及时检测到通信错误或损坏的合作伙伴系统。 2.从应用程序发送零长度帧通常会提供类似的结果。这将强制执行TCP PUSH和ACK段对,从而检测到丢失的会话。 3.应用程序级保持活动消息,用于发送和接收以轮询合作伙伴是否有活动响应。 4.一方定期发送心跳消息。
前两种方法不会导致通过通道传输的应用程序级信息发生任何变化,尽管它们必须触发传输空段。
最后两个选项会导致应用程序通信并提供更多信息。例如,如果主机应用程序停止响应,则前两个备选项无法检测到此故障模式。第四个选项隐式地起作用。发件人最终会收到错误消息,接收者应该期望周期性消息作为健康会话的指示。
如果使用更高级别的协议 - 例如RPC或REST,则可以使用返回某些良性内容的Ping()函数。
除非必须检测连接故障,否则通常更容易在必要时重新连接。选择取决于应用层协议和从要求中获得的端到端消息保证。

2
基本上,TCP连接会在路由器中创建链接状态。为了检测断开的连接(例如当一个对等方崩溃时(未发送适当的断开连接信号)),这些状态必须在一段时间内被清除。当发生这种情况时,您的TCP连接已经关闭。 虽然我不能确定这些超时时间有多长,但它们似乎取决于设备制造商和/或互联网服务提供商。我记得我的空闲SSH终端会话在以前的1&1互联网提供商下很快(不到15分钟的空闲时间)关闭,而在使用Kabel-BW提供的连接时可以保持几个小时... 最后,我与之前的发言者得出结论:心跳是检测连接是否仍然存活的好方法...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接