确保使用async_read读取数据

时间:2011-09-08 20:23:41

标签: c++ boost boost-asio

我目前正在极低带宽环境中测试我的网络应用程序。我目前有代码,通过确保我仍然收到信息来尝试确保连接良好。

传统上我通过在ReadHandler函数中记录时间戳来做到这一点,这样每次调用时我知道我已经在套接字上接收了数据。由于带宽非常低,这还不够,因为我的ReadHandler没有被足够频繁地调用。

我一直在想着编写我自己的完成条件函数(现在我正在使用tranfer_at_least(1)),认为它会被更频繁地调用,我可以在那里记录我的时间戳,但我想知道是否有这是其他一些更标准的方法。

3 个答案:

答案 0 :(得分:1)

我们在生产中遇到了类似的问题:我们的一些连接可能闲置数天,但我们必须尽快检测遥控器是否已经死亡。

我们通过启用TCP_KEEPALIVE选项解决了它:

boost::asio::socket_base::keep_alive option(true);
mSocketTCP.set_option(option);

必须附带新的启动脚本,该脚本将合理的值写入/proc/sys/net/ipv4/tcp_keepalive_*,默认情况下会有很长的超时时间(在LInux上)

答案 1 :(得分:1)

您可以使用read_some方法获取部分读取,并处理簿记。这比transfer_at_least(1)更有效,但你仍然需要跟踪发生了什么。

然而,更简洁的方法就是使用并发deadline_timer。如果计时器在你完成之前熄灭,那么花费太长时间并取消正在进行的操作。如果没有,只需停止计时器并继续。类似的东西:

boost::asio::deadline_timer t;
t.expires_from_now(boost::posix_time::seconds(20));
t.async_wait(bind(&Class::timed_out, this, _1));

// Do stuff.

if (!t.cancel()) {
   // Timer went off, abort
}


// And the timeout method

void Class::timed_out(error_code const& error)
{
    if (error == boost::asio::error::operation_aborted) return;
    // Deal with the timeout, close the socket, etc.
}

答案 2 :(得分:0)

我不知道如何在应用程序内处理网络的低延迟。您是否可以确定它是否是网络延迟,或者对等服务器或对等应用程序是否忙碌且反应迟缓。网络/服务器/应用程序被子是否重要?

即使您发现网络延迟并发现它很大,您打算做什么? 你无法改善这种状况。

考虑其他关键案例,这是您尝试处理的内容的一个子集 - 网络已关闭(例如,您断开了计算机的电缆连接)。既然它是你问题的一个子集,你也想要处理它。

让我们检查一下活动TCP连接的网络中断效果。您如何发现您的活动TCP连接仍然存在?调用send()会成功,但它只是说消息在内核的TCP传出队列中排队。 TCP堆栈将尝试发送它,但由于TCP ACK将不会被发送回来,您身边的TCP堆栈将尝试一次又一次地重新发送它。您可以在netstat输出中看到您的消息(Send-Q列)。

我知道以下处理方法:

  • 一种标准的方法是TCP保持活着提议@Cubby。

  • 另一种方法是实现Keep Alive机制。发送Keep Alive req消息,同伴有义务发回Keep Alive ack消息。

    如果在预定义超时后没有收到确认消息,请尝试多次发送保持活动请求N(例如N = 2)。如果仍然没有成功,请关闭套接字并再次打开。如果对等服务器不可用,您将无法打开连接,因为TCP 3方式握手需要对等方响应。