使用超时提升ASIO异步套接字

时间:2017-06-16 09:05:06

标签: sockets boost timeout asio

我正在尝试找到正确/规范的方法来实现下面的代码,该代码提供围绕异步asio方法的同步包装器以便超时。代码似乎有效,但我看过的所有例子都没有使用lambda中的boolean来终止运行i / o服务的do / while循环,因此我不确定这是否是正确的形式或者是否它将在未来产生意想不到的后果。有些人会这样做     而(IOService.run_one); 但永远不会终止。

编辑: 我试图效仿这个例子: http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/example/timeouts/blocking_tcp_client.cpp

但是在这段代码中,他们避免了使用\ n终结符读取的字节数。我需要读取的字节数,因此需要回调。

我已经看到许多其他解决方案使用boost async future以及其他方法,但它们似乎没有使用Ubuntu 16.04的gcc / boost标准版本进行编译,我想继续使用这些版本。

ByteArray SessionInfo::Read(const boost::posix_time::time_duration &timeout)
{

  Deadline.expires_from_now(timeout);
  auto bytes_received = 0lu;
  auto got_callback = false;

  SessionSocket->async_receive(boost::asio::buffer(receive_buffer_,
                               1024),
                               [&bytes_received, &got_callback](const boost::system::error_code &error, std::size_t bytes_transferred) {
                             bytes_received = bytes_transferred;
                             got_callback = true;
                           });
  do
  {
    IOService.run_one();
  }while (!got_callback);

  auto bytes = ByteArray(receive_buffer_, receive_buffer_ + bytes_received);
  return bytes;
}

2 个答案:

答案 0 :(得分:0)

我就是这样做的。触发的第一个事件导致io_service::run()返回。

ByteArray SessionInfo::Read(const boost::posix_time::time_duration &timeout)
{
  Deadline.expires_from_now(timeout);  // I assume this is a member of SessionInfo
  auto got_callback{false};
  auto result = ByteArray();

  SessionSocket->async_receive(  // idem for SessionSocket
    boost::asio::buffer(receive_buffer_, 1024),
    [&](const boost::system::error_code error, 
        std::size_t bytes_received) 
    {
      if (!ec)
      {
        result = ByteArray(receive_buffer_, bytes_received);
        got_callback = true;
      }
      Deadline.cancel();
    });

  Deadline.async_wait([&](const boost::system::error_code ec) 
  {
     if (!ec)
     {
       SessionSocket->cancel();
     }
  });        

  IOService.run();

  return result;
}

答案 1 :(得分:0)

阅读M. Roy的回答下面的对话,你的目标是确保这一点  IOService.run();返回。所有点都是有效的,boost::asio::io_service的实例每个执行线程只应运行一次(意思不是同时运行,但可以多次串行运行),因此必须知道它是如何使用的。也就是说,为了使IOService停止,我会修改M. Roy的解决方案:

ByteArray SessionInfo::Read(const boost::posix_time::time_duration &timeout) {
  Deadline.expires_from_now(timeout);
  auto got_callback{false};
  auto result = ByteArray();

  SessionSocket->async_receive(
      boost::asio::buffer(receive_buffer_, 1024),
      [&](const boost::system::error_code error, 
          std::size_t bytes_received)  {
        if (!ec) {
          result = ByteArray(receive_buffer_, bytes_received);
          got_callback = true;
        }
        Deadline.cancel();
      });

  Deadline.async_wait(
      [&](const boost::system::error_code ec) {
        if (!ec) {
          SessionSocket->cancel();
          IOService.stop();
        }
      });        

  IOService.run();
  return result;
}