【问题标题】:Boost asio async_write callback doesn't get calledBoost asio async_write 回调不会被调用
【发布时间】:2013-06-02 16:41:32
【问题描述】:

我正在尝试编写一个简单的服务器来异步发送消息,但是我的 async_write 回调没有被调用。顺便说一句,数据已成功传输到客户端。

首先,我的服务器初始化代码:

void Server::start()
{
    ioService = new boost::asio::io_service();
    acceptor = new tcp::acceptor(*ioService, tcp::endpoint(tcp::v4(), port));

    serverRunning = true;

    serverThread = new boost::thread(&Server::run, this);
    startAccept();
}

我的开始接受和接受处理程序方法:

void Server::startAccept()
{
    serverSocket = new tcp::socket(acceptor->get_io_service());

    acceptor->async_accept(*serverSocket,
        boost::bind(&Server::handleAccept, shared_from_this(),
            boost::asio::placeholders::error));
}

void Server::handleAccept( const boost::system::error_code& error )
{
    changeState(Connected);
}

handleAccept 方法在我连接时被调用,changeState 方法现在什么都不做。客户端连接后,我将一些数据放到toSend向量中,服务器的线程发送它们:

void Server::run(){
    while( serverRunning ){
        ioService->poll();

        if (toSend.size()>0 ){
            mtx.lock();
            for (int i=0; i<toSend.size(); i++){
              cout << "async write" << endl;
                boost::asio::async_write(*serverSocket, boost::asio::buffer(toSend.at(i)),
                        boost::bind(&Server::handleSend, shared_from_this(),
                            toSend.at(i),
                            boost::asio::placeholders::error,
                            boost::asio::placeholders::bytes_transferred));
            }
            toSend.clear();
            mtx.unlock();
        }
        usleep(1000);
    }
}

我可以看到标准输出上出现“异步写入”消息,并且客户端也收到了数据。我的 handleSend 方法现在只是一些 cout,但它永远不会被调用。为什么?

【问题讨论】:

    标签: c++ boost asynchronous boost-asio


    【解决方案1】:

    如果你真的想手动 poll io_service,在它得到一些工作后执行此操作,然后调用 reset between the iterations。

    此外,不要循环调用asio::async_write - 数据不会以正确的顺序到达。相反,要么准备一个缓冲区序列并立即发送,要么链接async_write - 完成处理程序 - async_write,如示例中所示。

    【讨论】:

    • 为什么不能循环调用async_write?异步帖子是先进先出完成的。
    • @Michael Mueller 帖子的 FIFO(顺便说一下,实现细节)在这里无关紧要。请注意,asio::async_write 是一个 composed operation,它通过多次调用流的 async_write_some() 来实现。如果一个人在一个循环中调用async_write,async_write_some 的调用链就会交错。
    • R 由于 async_write 是一个组合操作,因此在成功写入时会调用完成处理程序,这意味着另一端已为数据发送了相应的 ACK。这对于由多个 async_write_some 操作组成的较大消息是有问题的,因为无法保持硬件设备上的发送缓冲区已满。那么,有什么方法可以消除各个 async_write_some 调用之间不可避免的延迟,还是我们只需要接受它作为设计的一部分?
    • @Michael Mueller 在前一个完成之前无法调用 async_write_some 。但是你为什么要关心这个?您的基准测试是否表明您没有达到最大可能的吞吐量?
    • @Igor R 是的,我有数据证实一个 async_write 意味着端点之间的往返。在 Windows 上,一旦有足够的数据被确认,完成处理程序就会被调用,而不是在它被发布到硬件设备时。对于 Windows,只要数据不会被 ASIO 分块,我们就可以调用 async_write,但您需要非常小心。一般来说,有一个发送未完成是有意义的。使用多缓冲区调用确实可以提高性能,但您仍然需要为延迟付费。
    猜你喜欢
    • 2011-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多