0

我正在尝试找到正确/规范的方法来实现下面的代码,该代码提供了围绕异步 asio 方法的同步包装器,以便超时。代码似乎可以工作,但我看过的示例都没有使用 lambda 中的布尔值来终止运行 i/o 服务的 do/while 循环,所以我不确定这是否是正确的形式,或者它是否会有意想不到的后果。有些人会做一些事情,比如 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 异步期货以及其他方法的解决方案,但它们似乎无法与 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;
}
4

2 回答 2

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;
}
于 2017-08-18T17:08:01.617 回答
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;
}
于 2017-06-17T22:29:57.280 回答