我正在关注 ASIO 的 async_tcp_echo_server.cpp编写服务器的示例。
我的服务器逻辑如下所示(.cpp 部分):
1.服务器启动:
bool Server::Start()
{
mServerThread = std::thread(&Server::ServerThreadFunc, this, std::ref(ios));
//ios is asio::io_service
}
2.初始化接受器并监听传入连接:
void Server::ServerThreadFunc(io_service& service)
{
tcp::endpoint endp{ address::from_string(LOCAL_HOST),MY_PORT };
mAcceptor = acceptor_ptr(new tcp::acceptor{ service,endp });
// Add a job to start accepting connections.
StartAccept(*mAcceptor);
// Process event loop.Hang here till service terminated
service.run();
std::cout << "Server thread exiting." << std::endl;
}
3.接受连接并开始从客户端读取:
void Server::StartAccept(tcp::acceptor& acceptor)
{
acceptor.async_accept([&](std::error_code err, tcp::socket socket)
{
if (!err)
{
std::make_shared<Connection>(std::move(socket))->StartRead(mCounter);
StartAccept(acceptor);
}
else
{
std::cerr << "Error:" << "Failed to accept new connection" << err.message() << std::endl;
return;
}
});
}
void Connection::StartRead(uint32_t frameIndex)
{
asio::async_read(mSocket, asio::buffer(&mHeader, sizeof(XHeader)), std::bind(&Connection::ReadHandler, shared_from_this(), std::placeholders::_1, std::placeholders::_2, frameIndex));
}
所以 Connection 实例最终触发了 ReadHandler
回调,我在这里执行实际的读写操作:
void Connection::ReadHandler(const asio::error_code& error, size_t bytes_transfered, uint32_t frameIndex)
{
if (bytes_transfered == sizeof(XHeader))
{
uint32_t reply;
if (mHeader.code == 12345)
{
reply = (uint32_t)12121;
size_t len = asio::write(mSocket, asio::buffer(&reply, sizeof(uint32_t)));
}
else
{
reply = (uint32_t)0;
size_t len = asio::write(mSocket, asio::buffer(&reply, sizeof(uint32_t)));
this->mSocket.shutdown(tcp::socket::shutdown_both);
return;
}
}
while (mSocket.is_open())
{
XPacket packet;
packet.dataSize = rt->buff.size();
packet.data = rt->buff.data();
std::vector<asio::const_buffer> buffers;
buffers.push_back(asio::buffer(&packet.dataSize,sizeof(uint64_t)));
buffers.push_back(asio::buffer(packet.data, packet.dataSize));
auto self(shared_from_this());
asio::async_write(mSocket, buffers,
[this, self](const asio::error_code error, size_t bytes_transfered)
{
if (error)
{
ERROR(200, "Error sending packet");
ERROR(200, error.message().c_str());
}
}
);
}
}
现在,问题来了。服务器从客户端接收数据并发送,使用sync asio::write
,很好。但是当涉及到 while 循环内的 asio::async_read
或 asio::async_write
时,该方法的 lambda 回调永远不会被触发,除非我将 io_context( ).run_one();
紧随其后。我不明白为什么我会看到这种行为。我确实在 acceptor init 之后立即调用了 io_service.run()
,所以它会阻塞直到服务器退出。据我所知,我的代码与 asio 示例的唯一区别是我从自定义线程运行我的逻辑。
最佳答案
您的回调没有返回,阻止事件循环执行其他处理程序。
一般来说,如果你想要一个异步流程,你会链接回调,例如回调检查 is_open()
,如果为真,则调用 async_write()
并将其自身作为回调。
无论哪种情况,回调都会返回。
这允许事件循环运行,调用您的回调,等等。
简而言之,您应该确保您的异步回调始终在合理的时间范围内返回。
关于c++ - 不处理 asio 异步操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45674808/