在async_accept()
socket
对象移动到session
对象(处理所有async_read()
对象之后的boost :: asio standard examples中通过将其初始化为以下内容来调用:
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会在客户端连接后立即提高到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();
}
提升1.49
修改
感谢您的回答!我最后移动socket_
才使用它:
tcp::socket *socket = new tcp::socket(std::move(socket_));
也讨论了同样的问题
答案 0 :(得分:3)
如果传递给basic_socket_acceptor::async_accept()
的 peer 套接字未打开,则它将在async_accept()
操作期间打开。否则,如果 peer 已经打开,那么 handler 将被发布到io_service
进行调用,错误代码为boost::asio::error::already_open
。因此,发布的代码会导致紧密的异步调用链形成:
async_accept()
操作,导致socket_
被打开。async_accept()
处理程序调用{{1}},启动do_accept()
操作。async_accept()
已经打开,导致socket_
操作将其处理程序发布到async_accept()
,错误为io_service
。在官方示例中未观察到此行为,因为socket's move operator导致移动的对象处于与使用basic_stream_socket(io_service&)
构造函数构造的状态相同的状态。因此,移动的对象处于关闭状态,并准备好接受。
答案 1 :(得分:1)
您在所有地方都使用单socket_
,因此当接受连接时,您的处理程序再次调用do_accept()并使用相同的socket_
,然后一次又一次地接受它。 ..
您可能需要始终使用如下所示的新套接字:
void do_accept()
{
boost::shared_ptr<tcp::socket> psocket(new tcp::socket(io_service));
acceptor_.async_accept(*psocket, boost::bind(&Server::handleAccept, this, psocket, _1));
}
void handleAccept(boost::shared_ptr<tcp::socket> psocket, const boost::system::error_code& ec)
{
if (!ec) {
char* buf = new char[5];
boost::asio::async_read(
*psocket,
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();
}