如何检测 TCP 连接中的网线是否已拔出?
我有一个 C++ 网络应用程序,它接受来自客户端的 TCP 连接,然后在套接字上等待,直到客户端决定发送数据(有时他们很长时间都不会发送任何东西,这没关系).
I have a C++ networking application that accepts TCP connections from clients and then waits on the socket until the client decides to send data (sometimes they won't send anything for a long time and thats OK).
它主要在客户端崩溃或机器关闭时检测错误情况,但是当连接到客户端的网络电缆被拔下时,它需要很长时间才能注意到,我希望它尽快注意到这种情况.
It mostly detects error conditions when clients crash or machines are turned off, but it takes many minutes to notice when the network cable to the client has been unplugged and I would prefer it to notice this condition as soon as possible.
我无法控制客户端,也无法让他们发送类似ping"的信息.我的服务器确实向客户端发送了一个ping"数据包(但它们不会发送响应),但即使拔下电缆,write() 也会返回正确的字节数(我看到 TCP 堆栈发送重试Wireshark 中的数据包).
I don't have control over the clients and I can't make them send something like a "ping". My server does send out a "ping" packet to the to the clients (but they won't send a response), but even when the cable is unplugged write() returns the correct number of bytes (I see the TCP stack sending retry packets in Wireshark).
发现连接丢失的最佳方法是什么?如果我能在 write() 调用中检测到它会最方便.
What is the best way to notice the loss of connection ? It would be most convenient if I could detect it on the write() call.
我需要它在 Windows 和 Linux 上工作.
I need this to work on Windows and on Linux.
推荐答案
很遗憾,无法区分另一端被拔出的电缆与其他任何丢包原因.话虽如此,您可以将另一端的连接丢失近似为在足够长的时间段(例如 T)内发生的无限丢包".TCP 跟踪数据包丢失,因此执行此操作的一般方法是:
Unfortunately, there is no way to distinguish the cable being pulled out at the other end from any other reason for packet loss. Having said that, you can approximate loss of connectivity at the other end as "indefinite packet loss" occurring over a sufficiently long period of time (say T). TCP tracks packet loss, so the general approach for doing this would be:
- 获取连接中未确认的字节数(假设为 B)
- 发送数据,大小 = N
- 设置 timeout = T,当它触发时,再次检查未确认的字节数.如果是B+N,则假设对方已经失去连接.此时,您可以尝试 ICMP echo 来验证您的假设.
获取连接的 TCP 特定信息不是 UNIX 上的标准接口,也绝对不能移植到 Windows.在 Linux 上,有一个名为 TCP_INFO 的套接字选项,您可以通过 getsockopt() 调用它.谷歌应该给你一些例子.我不知道 Windows 上是否有等效选项.
Getting TCP-specific information for a connection is not a standard interface on UNIX, and definitely not something portable to Windows. On Linux, there's a socket option called TCP_INFO, which you can call via getsockopt(). Google should give you some examples. I don't know if there's an equivalent option on Windows.
另一种方法(即近似跟踪连接丢失)是通过 RAW 套接字.打开一个 RAW 套接字并对其进行过滤以仅接收用于您的连接的 TCP 流量.然后,与其从 TCP 获取信息以确定您是否从另一端获取任何信息,不如等待从另一端接收 any 数据包.如果在规定的时间内得到了东西,那就说明对端还在.
Another way to do this (i.e. approximate tracking of connectivity loss) is via RAW sockets. Open a RAW socket and filter it to receive only TCP traffic for your connection. Then rather than fetching information from TCP to determine if you are getting anything from the other end, simply wait to receive any packet from the other side. If you get something in the stipulated period, then it means the peer is still up.
相关文章