Sockets 如何使用TCP keep_alive属性在对等方无响应时获得通知?

Sockets 如何使用TCP keep_alive属性在对等方无响应时获得通知?,sockets,tcp,boost-asio,tcp-keepalive,Sockets,Tcp,Boost Asio,Tcp Keepalive,场景: 我有一个客户端和服务器编写使用。一般来说,连接和通信部分工作得很好 我已经在两侧写了一个看门狗,它以每2秒的间隔向对等方发送虚拟数据包。看门狗的目标是,如果相关对等方在接下来的2秒内没有收到预期的虚拟数据包,则会报告连接错误。这对我来说更为重要,因为可能会发生这样的情况:两个对等方没有出于任何用户目的处理数据包,但如果任何一个对等方出现故障,则每个对等方都必须报告连接错误。对等机可能会因为内核崩溃而崩溃,在这种情况下,对等机不可能发送消息。这当然是一个经典问题,它甚至存在于asio和TC

场景:
我有一个客户端和服务器编写使用。一般来说,连接和通信部分工作得很好

我已经在两侧写了一个看门狗,它以每2秒的间隔向对等方发送虚拟数据包。看门狗的目标是,如果相关对等方在接下来的2秒内没有收到预期的虚拟数据包,则会报告连接错误。这对我来说更为重要,因为可能会发生这样的情况:两个对等方没有出于任何用户目的处理数据包,但如果任何一个对等方出现故障,则每个对等方都必须报告连接错误。对等机可能会因为内核崩溃而崩溃,在这种情况下,对等机不可能发送消息。这当然是一个经典问题,它甚至存在于asio和TCP之外

我的看门狗工作得很好。没有问题

但是,最近我读到了Socket中的功能。我尝试了以下代码,似乎可以通过使用
boost::asio
从代码中获取套接字的本机句柄,在TCP套接字上创建一个名为keep_alive的属性

boost::asio::io_service      ioService;
boost::asio::ip::tcp::socket mySocket(ioService);

int on = 1;
int delay = 120;
setsockopt(mySocket.native_handle(), SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
setsockopt(mySocket.native_handle(), IPPROTO_TCP, TCP_KEEPALIVE, &delay, sizeof(delay));
问题:
上面的代码在macOS、Linux和iOS上编译得很好。看起来不错。但是,我如何从中受益?当对等机停机时,这是否会给我一个回调或事件?这是否让我免于写我上面描述的看门狗

我使用了
boost::asio::async\u connect
连接到对等机。当perr在定义的超时时间间隔后停止时,我可以得到对connectionHandler的回调吗


设置了
保持活动状态
选项后,我如何知道我的对等方不再响应?

如果在异步操作挂起时检测到断开连接,则将使用相应的错误代码调用套接字的完成处理程序

问题是TCP keep_alive选项并不总是检测断开连接

通常,除了实现应用程序级ping/heartbeat之外,没有可靠的方法来检测突然断开


您还可以看到。

您不需要原始
设置sockopt
,您可以使用
当对等机停机时,这是否会给我一个回调或事件?
我假设它失败,您的读写操作带有退出代码。
如果我的对等机处于空闲状态且没有进行任何读写操作,它不会向我发送事件。
正确,但这将在何时发生?您通常会有一个等待数据的读取,否?TCP keepalive(a)在默认情况下是关闭的(b)在启用时,默认情况下每隔两小时运行一次(c)在下次使用套接字进行I/O时,如果检测到死机,会导致连接重置。@AdeleGoldberg我对它的工作方式很感兴趣。你能写一个(非常)简短的总结吗?TCP保持活动总是检测到断开连接。问题是,默认情况下,它的计时器设置为2小时不活动,然后发送探测。您可以将计时器配置为一个更低的值。@Maxim Egorushkin据我所知,我曾尝试过(在Windows上)这样做,但它仍然没有涵盖所有场景。即使是这样,配置系统范围的参数听起来也不是最理想的解决方案。超时是Linux上的每个套接字选项,不确定Windows。我在macos、android和ios上尝试了tcp keep_。它似乎能为我检测到所有断开的连接。我已经对它进行了非常严格的测试。我想这对我来说是可行的。我不是在windows上测试。但我已经在linux端测试了类似于
killall-9myapp
pkillmyapp
的场景。这也很好地保持了_的活力,以检测破损。