场景:
我有一个使用boost::asio 1.63编写的客户端和服务器。一般来说,连接和通信部分工作得很好。
我在双方都写了一个看门狗,每个看门狗以2秒的间隔向对等方发送伪数据包。看门狗的目标是,如果相关对等端在接下来的2秒内没有收到预期的伪数据包,则报告连接错误。这对我来说更为重要,因为可能发生的情况是,这两个对等端没有出于任何用户目的处理数据包,但如果任何一个对等端出现故障,它们都需要报告连接错误。对等端可能会因为内核崩溃而宕机,在这种情况下,该对等端不可能发送消息。当然,这是一个经典的问题,甚至存在于asio和TCP之外。
我的看门狗工作得非常好。一点问题都没有。
但是,最近我读到了套接字中的keep_alive功能。我尝试了以下代码,似乎可以通过使用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_connect
连接到对等端。当perr在定义的超时间隔后关闭时,我能得到对connectionHandler的回调吗?
设置了keep_alive
选项后,我如何才能知道我的对等端不再响应?
如果在异步操作挂起时检测到非控制,则将调用套接字的完成处理程序并返回相应的错误代码。
问题是TCP keep_alive选项并不总是检测断开连接。
通常,除了实现应用程序级别的ping/heartbeat之外,没有可靠的方法来检测突然断开连接。
你也可以看到这个线程。