使用Boost :: Asio套接字异步和同步操作

时间:2015-12-01 14:52:35

标签: c++ sockets boost boost-asio

我是Boost C ++的新手,用它编写类似服务器的应用程序,我想知道是否可以同时使用 boost::asio::ip::tcp::socket::async_read_some(...)boost::asio::ip::tcp::socket::write_some(...)

在我的场景中,Connection对象通过以下方式连续侦听:

    void Connection::doRead()
{
    auto self(shared_from_this());
    socket_.async_read_some(boost::asio::buffer(data_rx_, max_length),
        [this, self](boost::system::error_code ec, std::size_t length)
        {
          if (!ec)
          {
              afterReading(length);
              doRead();
          }
        });
}

同时,异步函数回调(在不同的线程中运行)可以在Connection“读取”时调用socket_.read_write

我已经阅读了各种Boost :: Asio文档,但这种情况从未被涵盖过。

这是允许的吗?如果没有,应该采取什么措施来避免呢?

编辑:

我已经按照建议阅读了各种答案,包括:Why do I need strand per connection when using boost::asio?,但仍未找到答案,因为未指定混合异步和同步(由不同线程调用)调用是否安全

1 个答案:

答案 0 :(得分:2)

这不安全。

这个answer详细介绍,但总而言之,多个线程同时进行调用是不安全的,异常多个同步调用可能如果操作系统支持,请保持安全。如果一个线程在套接字上启动异步操作而另一个线程在同一个套接字上执行同步操作,那么它就属于前一种情况并且不安全。

最优雅的解决方案是避免混合同步和异步操作。

  • 如果使用同步操作且操作系统不支持并发同步操作,则执行显式锁定,例如使用互斥锁。
  • 如果使用异步操作和多个线程,则使用显式strand来防止并发调用处理程序。

此外,通过利用Boost.Asio对futures的支持,可以同步阻止等待异步操作完成。这种方法可以允许用户向用户公开同步阻塞API,但在内部使用异步操作。需要在一个strand中调用启动操作(async_*),如果调用者没有在strand的上下文中运行,则需要使用某种形式的同步来允许调用者等待Asio创造未来的对象。