boost.asio async_receive永不解决

时间:2018-09-20 08:24:04

标签: c++ boost boost-asio asio

我正在尝试通过实现回显服务器来了解asio的工作原理。但是它从不回声!

这是我的代码(请忽略资源泄漏):

#include<boost/asio.hpp>
#include<cstdio>

boost::asio::io_service ioService;

void echo(boost::asio::ip::tcp::socket* socket) {
    char* buf = new char[1024];
    socket->async_receive(boost::asio::buffer(buf, 1023), [buf, socket](auto ec, auto s) {
        if (ec) {
            std::printf("read failed: %s!\n", ec.message().data());
        }
        else
        {
            buf[s] = '\0';
            std::printf("read:%s!\n", buf);
            socket->async_send(boost::asio::buffer(buf, s), [socket](auto ec, auto s) {
                if (ec) {
                    std::printf("write failed: %s!\n", ec.message().data());
                }
                else {
                    echo(socket);
                }
            });
        }
    });
}

void accept(boost::asio::ip::tcp::acceptor& acceptor) {
    auto socket = new boost::asio::ip::tcp::socket{ ioService };
    acceptor.async_accept(*socket, [socket](auto ec) {
        if (ec) {
            std::printf("accept failed:%s!\n", ec.message().data());
        }
        else {
            std::printf("accept %s!", socket->remote_endpoint().address().to_string().data());
            echo(socket);
        }
    });
}

int main() {
    try {
        boost::asio::ip::tcp::acceptor acceptor{ ioService, boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 8000) };
        accept(acceptor);
        while (true)
        {
            ioService.poll();
        }
    }
    catch (std::exception&e) {
        std::printf("error: %s\n", e.what());
    }
}

我正在使用Java TCP客户端(我已经使用Java TCP回显服务器对其进行了测试)来连接服务器并将消息发送到该服务器。唯一起作用的是accept函数。我可能在哪里弄错了?

1 个答案:

答案 0 :(得分:0)

问题是:

    while (true)
    {
        ioService.poll();
    }

您要删除while循环并使用“运行”方法:

     ioService.run();

实际的问题是,在调用之前,必须先调用“ restart”方法(或对于较旧版本的asio使用较旧的reset方法,这在您的代码中是如此)再次投票。循环的另一个问题是,当无事可做时,正在运行的CPU将处于100%状态,因为它处于硬循环中而无所事事...如果您使用“运行”方法,则CPU将使用无事可做时为0%。

例如

while (true)
{
    ioService.poll();
    ioService.reset();
}

引用ASIO文档:

  

此函数必须在第二个或以后的任何一组之前调用   调用run(),run_one(),poll()或poll_one()函数   当这些功能的先前调用由于   io_context被停止或无法工作。致电后   restart(),io_context对象的stopped()函数将返回   错误。