代码之家  ›  专栏  ›  技术社区  ›  Michael IV

未处理asio异步操作

  •  1
  • Michael IV  · 技术社区  · 7 年前

    我正在关注ASIO的 async_tcp_echo_server.cpp

    我的服务器逻辑如下(.cpp部分):

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

    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));
    }
    

    因此连接实例最终触发 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 好的但是说到 asio::async_read asio::async_write 在while循环中,该方法的lambda回调永远不会被触发,除非我将 io_context().run_one(); 紧接着。我不明白为什么我会看到这种行为。我确实打过电话 io_service.run() 就在acceptor init之后,所以它在那里阻塞,直到服务器退出。据我所知,我的代码与asio示例的唯一区别在于,我从自定义线程运行我的逻辑。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Hasturkun    7 年前

    回调没有返回,阻止事件循环执行其他处理程序。

    一般来说,如果您想要异步流,您将链接回调,例如回调检查 is_open() ,如果为true async_write()

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

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