2016-11-22 23 views
-1

我试图搜索这很多。我是network+tcp-sockets编程的新手。boost :: asio ::在TCP客户端应用程序中读取需要很长时间才能返回连接丢失

我正在使用TCP sockets通过网络传输数据。我有一个host app &一个client app都使用boost::asio,两端传递数据写入C++ &。

client app中,我使用boost::asio::read在我的C++客户端应用程序中读取socket中的一些数据。主机应用程序在另一台机器上运行。

以下是我读取一些数据的代码&尝试确定是否有错误。

boost::system::error_code error_code; 
std::size_t data_received = boost::asio::read(socket, boost::asio::buffer(&data_to_read, sizeof(data_to_read)), error_code); 
if (error_code == boost::asio::error::eof) { 
    //ends here if the host app closes the socket 
    //log error & return 
} 

if (data_received <= 0) { 
    //log error & return 
} 

我收到boost::asio::error::eof当主机应用程序关闭套接字和它的作品来更新我的UI显示我已经失去了联系。

但是,这里是问题:当network/wifi在主机应用程序上关闭,然后boost::asio::read需要很长时间才能返回。有点像2分钟。然后在长时间延迟后我得到一个boost::asio::error::eof错误。奇怪!我无法承受这种延迟,因为我需要为用户快速更新UI,因此无法从host app获取数据。

为什么asio在网络关闭或连接断开时会快速返回?有没有其他的方式来检测这个或处理这个?

PS:注意boost::asio::read是一个阻塞调用,但如果它需要时间来恢复,因为我在一个worker thread这样它不锁我的UI线程。

+0

什么是本地IP?因为如果这是回环,那么它与WiFi无关。回送“始终”工作 – sehe

+0

是@sehe。但是,本地IP是不必要的额外信息。因此,我从我的问题中删除了它 –

+0

由于您没有阻塞UI线程,为什么不让UI线程更新UI并让用户知道无法从主机获取数据?在阻止读取被阻止时,您可以选择做什么。如果您不想阻止此线程,直到可以完成读取或明确失败,请不要进行阻止读取调用。你得到了你所要求的 - 如果你不喜欢它,请寻求别的东西。 –

回答

2

即使面对看似灾难性的问题,TCP的设计也是“可靠的”。它在连接的另一端没有响应时通过一系列定时器和重传来完成。重传的频率和时间取决于操作系统。连接报告失败之前可能需要几分钟甚至几小时。

内部套接字有一组选项来控制可以在套接字上设置的保持活动设置(如果boost :: asio公开它们)。快速谷歌搜索'tcp keepalive'带来了一堆例子。

另一个选择是实现自己的计时机制,你经常通过TCP连接&自己定义适当的时机应该什么送包&响应。

+0

我搜索了'tcp :: no_delay'。发现几个链接像一个[这里](http://stackoverflow.com/questions/5706641/asio-iptcpiostream-and-tcp-nodelay)。 'boost :: asio'似乎也支持它。但似乎我可以在使用'boost :: asio :: ip :: tcp :: iostream'来读取我的缓冲区时使用它。在我的代码中,如果我尝试设置'tcp :: no_delay(true)',那么我应该在每次'boost :: asio :: read'调用之前设置它吗? –

+1

@SegmentationFault'tcp :: no_delay'正在解决一个不同的问题。 TCP keepalive是一种可以更快速地报告故障的ping。如果你有对协议的控制,最好的方法就是像@evan描述的那样实现你自己的连接测试机制。 – janm

+1

我还应该提到,保持活动设置与平台相关,其可配置性也是如此。 – evan

相关问题