asio异步操作未处理

时间:2017-08-14 12:42:41

标签: c++ boost-asio

我正在关注ASIO的async_tcp_echo_server.cpp示例来编写服务器。

我的服务器逻辑看起来像这样(.cpp部分):

1.Server startup:

bool Server::Start()
{
  mServerThread = std::thread(&Server::ServerThreadFunc, this, std::ref(ios));
  //ios is asio::io_service
}

2.Init acceptor并侦听传入连接:

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_readasio::async_write时,方法的lambda回调永远不会被触发,除非我在此之后立即放置io_context().run_one();。我不明白为什么我会看到这种行为。我在acceptor init之后立即调用io_service.run(),因此它会阻塞,直到服务器退出。据我所知,我的代码与asio示例的唯一区别在于我从自定义线程运行我的逻辑。

1 个答案:

答案 0 :(得分:1)

您的回调未返回,阻止事件循环执行其他处理程序。

一般来说,如果你想要一个异步流程,你可以链接回调,例如回调检查./obj,如果为true则调用is_open()并将其自身作为回调。

在任何一种情况下,回调都会返回。

这允许事件循环运行,调用回调等等。

简而言之,您应确保异步回调始终在合理的时间范围内返回。