c++ - 不处理 asio 异步操作

标签 c++ boost-asio

我正在关注 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_readasio::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/

相关文章:

php - 为什么 php 扩展开发与 c++ 开发有如此大的不同?

ssl - 使用客户端证书 sslv3 握手失败 boost asio GET

c++ - 如何使 boost::asio::serial_port_base::flow_control 使用硬件流控制?

C++检测文本文件中的空间

c# - 此 Canon SDK C++ 代码片段的等效 C# 代码是什么?

c++ - 不理解 boost error_codes

c++ - Boost.Asio SSL 上下文 load_verify_paths 未加载证书

c++ - 将 ASIO 链接到项目而不在 Visual Studio 中 boost

c++ - STL 堆栈和 top() 函数的问题

c++ - C++ std::unordered_map 与 Kotlin/Java HashMap 的性能对比