在 boost::asio 中 standard examples在 async_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
。因此,发布的代码导致形成一个紧密的异步调用链:
- 第一次调用
async_accept()
操作,导致socket_
打开。 async_accept()
处理程序调用do_accept()
,启动async_accept()
操作。socket_
已经打开,导致async_accept()
操作将其处理程序发布到io_service
中,并出现boost 错误::asio::error::already_open
.- 异步调用链从第 2 步开始。
官方示例中未观察到此行为,因为 socket's move operator使移出的对象处于与使用 basic_stream_socket(io_service&)
构建时相同的状态构造函数。因此,被移出的对象处于关闭状态,并准备接受。
关于c++ - boost::asio::async_read 在简单示例中 100% CPU 使用率,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20648916/