c++ 关闭并重新打开Boost asio接收器

r1zhe5dt  于 2023-01-18  发布在  其他
关注(0)|答案(1)|浏览(151)

我一直在使用boost中针对单线程服务器的以下示例:https://www.boost.org/doc/libs/1_81_0/doc/html/boost_asio/example/cpp03/http/server/
我修改了服务器类,以便可以启动、结束和重新启动服务器。

server_impl::server_impl(
    const std::string& address,
    const std::string& port,
    const std::shared_ptr<boost::asio::io_context>& io_context,
    const std::shared_ptr<connection_manager>& connection_manager,
    const std::shared_ptr<request_handler>& request_handler) :
        io_context_(io_context),
        acceptor_(*io_context_),
        connection_manager_(connection_manager),
        new_connection_(),
        request_handler_(request_handler),
        address_(address),
        port_(port)
{
}

void server_impl::start_server()
{
    // Open the acceptor with the option to reuse the address (i.e. SO_REUSEADDR).
    boost::asio::ip::tcp::resolver resolver(*io_context_);
    boost::asio::ip::tcp::endpoint endpoint =
        *resolver.resolve(address_, port_).begin();
    acceptor_.open(endpoint.protocol());
    acceptor_.set_option(boost::asio::ip::tcp::acceptor::reuse_address(true));
    acceptor_.bind(endpoint);
    acceptor_.listen();
    start_accept();
}

void server_impl::end_server()
{
    /* The server is stopped by cancelling all outstanding asynchronous
       operations */
    acceptor_.close();
    connection_manager_->stop_all();
}

void server_impl::start_accept()
{
    new_connection_.reset(new connection_impl(
        io_context_,
        connection_manager_,
        request_handler_));
    acceptor_.async_accept(
        new_connection_->socket(),
        boost::bind(
            &server_impl::handle_accept,
            this,
            boost::asio::placeholders::error));
}

void server_impl::handle_accept(const boost::system::error_code& e)
{
    /* Check whether the server was stopped before this completion handler had a
       chance to run. */
    if (!acceptor_.is_open())
    {
        return;
    }

    if (!e)
    {
        connection_manager_->start(new_connection_);
    }

    start_accept();
}

void server_impl::serve_static(const std::string& path)
{
    request_handler_->serve_from_directory(path);
}

你可以看到我把解析和监听从构造函数移到了start_server函数,然后把handle_stop的内容移到了end_server
如果我只是启动服务器并像这样结束它一次(使用一个线程在30秒后结束,只是为了测试):

int main()
{
    server->serve_static("/path/to/html");
    server->start_server();

    std::thread t([&server](){sleep(30); server->end_server();});

    io_context->run();

    t.join();
}

但是如果我尝试在服务器停止后重新启动它,io_context->run();会立即返回,我认为它应该阻塞,因为async_accept在接受器上再次被调用:

int main()
{
    server->serve_static("/path/to/html");
    server->start_server();

    std::thread t([&server](){sleep(30); server->end_server();});

    io_context->run();

    t.join();

    server->start_server();

    io_context->run();
}

服务器在前30秒工作,然后像预期的那样停止,但是当再次启动时,run立即返回,并且不会再次启动。

bfrts1fy

bfrts1fy1#

根据升压文档:
run()run_one()poll()poll_one()的后续调用将立即返回,除非之前调用了restart()

相关问题