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

Fra*_*cia 5 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();
          }
        });
}
Run Code Online (Sandbox Code Playgroud)

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

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

这是允许的吗?如果不是,应该怎么做才能避免它?

编辑:

我已经按照建议阅读了各种答案,包括:为什么在使用 boost::asio 时每个连接都需要链?,但仍然找不到答案,因为它没有指定混合异步和同步(由不同线程调用)调用是否安全。

Tan*_*ury 5

这是不安全的。

这个答案很详细,但总而言之,多个线程并发调用是不安全的,但如果操作系统支持多个同步调用可能是安全的。如果一个线程在某个套接字上发起异步操作,而另一个线程正在同一个套接字上执行同步操作,则属于前一种情况,并且不安全。

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

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

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