c++ - boost::asio::async_read 在简单示例中 100% CPU 使用率

标签 c++ sockets networking boost boost-asio

在 boost::asio 中 standard examplesasync_accept() 之后,socket 对象移动到 session 对象(它处理所有 async_read() 调用)通过如下初始化它:

std::make_shared<session>(std::move(socket_))->start();

并且在构造一个session 时它又在移动(不是冗余的吗?):

session(tcp::socket socket)
  : socket_(std::move(socket))

然后从客户端读取如下:

boost::asio::async_read(socket_, ...

一切顺利。但是,当我尝试使 async_read() 不是来自 session 对象,而是直接来自 async_accept() 并使用它时 socket 对象,客户端连接后 CPU 立即 boost 到 100%。为什么?

#include <boost/asio.hpp>
using boost::asio::ip::tcp;

class Server
{
public:
  Server(boost::asio::io_service& io_service,
         const tcp::endpoint& endpoint)    
    : acceptor_(io_service, endpoint),
      socket_(io_service)
  {
    do_accept();
  }

private:
  void do_accept()
  {
    acceptor_.async_accept(socket_,
       [this](boost::system::error_code ec)
       {
         if (!ec) {
           char* buf = new char[5];
           boost::asio::async_read(socket_,
              boost::asio::buffer(buf, 5),
              [this, buf](boost::system::error_code ec, std::size_t)
              {
                if (!ec) {
                  std::cout.write(buf, 5);
                  std::cout << std::endl;
                }
                delete[] buf;
              });
         }
         do_accept();
       });
  }

  tcp::acceptor acceptor_;
  tcp::socket socket_;
};

int main(int argc, char* argv[])
{
  int port = 22222;
  boost::asio::io_service io_service;
  tcp::endpoint endpoint(tcp::v4(), port);
  new Server(io_service, endpoint);
  io_service.run();
}

boost 1.49

编辑

感谢您的回答!我最终在使用它之前移动了 socket_:

tcp::socket *socket = new tcp::socket(std::move(socket_));

Repeated std::move on an boost::asio socket object in C++11 也讨论了同样的问题

最佳答案

如果 peer 套接字传递给 basic_socket_acceptor::async_accept()未打开,则在 async_accept() 操作期间将打开。否则,如果 peer 已经打开,则 handler 将被发布到 io_service 以进行调用,错误代码为 boost: :asio::error::already_open。因此,发布的代码导致形成一个紧密的异步调用链:

  1. 第一次调用async_accept()操作,导致socket_打开。
  2. async_accept() 处理程序调用 do_accept(),启动 async_accept() 操作。
  3. socket_ 已经打开,导致 async_accept() 操作将其处理程序发布到 io_service 中,并出现 boost 错误::asio::error::already_open.
  4. 异步调用链从第 2 步开始。

官方示例中未观察到此行为,因为 socket's move operator使移出的对象处于与使用 basic_stream_socket(io_service&) 构建时相同的状态构造函数。因此,被移出的对象处于关闭状态,并准备接受。

关于c++ - boost::asio::async_read 在简单示例中 100% CPU 使用率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20648916/

相关文章:

c++ - 这个类真正做什么?

c - 如果服务器关闭,则阻止 recv 调用挂起

java - 如何在具有单工连接的设备上读取和写入 Java ME 中的网络套接字?

objective-c - 列出网络适配器

networking - 将自定义路由添加到 GKE Pod

c++ - 在 C++ 中,所有键都可以表示为单个字符吗?

c++ - 如何在我的 iPhone 应用程序中使用 C++ STL 容器?

c++ - 我怎样才能完全杀死一个 gnome 终端?

javascript - 快速路由socket.io发出客户端未捕获的数据

c++ - 通过套接字传输大型阵列的最快方法