如何检测TCP连接中是否已拔下网络电缆?

时间:2013-01-09 01:35:29

标签: c++ sockets tcp network-programming

我有一个C ++网络应用程序,它接受来自客户端的TCP连接,然后在套接字上等待,直到客户端决定发送数据(有时他们不会发送任何东西很长时间,没关系)。

它主要检测客户端崩溃或计算机关闭时的错误情况,但需要花费很多分钟才能注意到客户端的网络电缆已拔下,我希望它能尽快注意到这种情况。

我无法控制客户端,我无法让他们发送类似“ping”的内容。我的服务器向客户端发送“ping”数据包(但它们不会发送响应),但即使拔掉电缆,write()也会返回正确的字节数(我看到TCP堆栈发送重试) Wireshark中的数据包)。

注意失去连接的最佳方法是什么?如果我可以在write()调用中检测到它,那将是最方便的。

我需要这个在Windows和Linux上运行。

3 个答案:

答案 0 :(得分:3)

抱歉,没有ping / keepalive,无法及时检测到异常断开连接。即使操作系统也不总是知道电缆已被拉动。这就是为什么write()仍然有效 - 套接字很乐意缓冲其传出缓冲区中的数据,等待稍后发送它,因为套接字状态尚未被操作系统无效。最终,套接字将在内部超时,此时操作系统最终可以使连接无效并让套接字在后续操作中报告错误。但是,你可能已经注意到这可能需要很长时间。

由于您无法发送应用程序层ping,请尝试至少启用套接字层保持活动。这可能有所帮助。仅在Windows 2000+上,您可以通过SIO_KEEPALIVE_VALS使用WSAIoctl()套接字选项,它允许您设置保持活动的实际计时器值。在所有平台上,您可以通过SO_KEEPALIVE使用setsockopt()选项,但这不允许您配置计时器值,因此使用默认值。

答案 1 :(得分:3)

不幸的是,没有办法区分在另一端拉出的电缆与丢包的任何其他原因。话虽如此,您可以将另一端的连接丢失近似为在足够长的时间段内发生的“无限期数据包丢失”(比如说T)。 TCP跟踪数据包丢失,因此执行此操作的一般方法是:

  • 获取连接中未分组的字节数(比如说是B)
  • 发送数据,尺寸= N
  • 设置超时= T,当它触发时,再次检查未包装的字节数。如果它是B + N,则假设另一方已失去连接。此时,您可以尝试使用ICMP echo来验证您的假设。

获取连接的TCP特定信息不是UNIX上的标准接口,绝对不能移植到Windows。在Linux上,有一个名为TCP_INFO的套接字选项,您可以通过getsockopt()调用它。谷歌应该给你一些例子。我不知道Windows上是否有相同的选项。

另一种方法(即连接丢失的近似跟踪)是通过RAW套接字。打开RAW套接字并对其进行过滤,以仅接收连接的TCP流量。然后,而不是从TCP获取信息以确定您是否从另一端获得任何内容,只需等待从另一端接收任何数据包。如果你在规定的时间内得到了什么,那就意味着同伴仍在运转。

答案 2 :(得分:1)

你的问题非常复杂。您和您的客户之间可能会出现很多问题。更多的只是一个“拔掉插头”'电缆。

如果您只是想知道您的用户是否仍在线,您可以构建新的TCP连接。因为您需要完成三次握手才能成功构建TCP连接,因此您知道在成功初始化连接时客户端处于联机状态。问题是,如果要保持当前连接处于活动状态,则需要另一个端口。在你的情况下,不知道这是否是一个问题。

但是听到它的声音,你并没有真正从你的客户端发送和接收数据(除了一些ping数据)。因此,您可以简单地将应用程序设置为循环以设置TCP连接(前2个步骤 - 因此接收ACK - 应该足以确定您的客户端是否仍在处理网络数据)每X秒。如果你在X毫秒内没有收到回复,那么你可以非常可靠地说出你的客户或其中的任何东西都停止了#34;工作"。

希望这会有所帮助。如果没有,请提供有关您的工具正在做什么的更多信息。