Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Close and reopen boost asio acceptor

I have been using this example from boost for a single threaded server: https://www.boost.org/doc/libs/1_81_0/doc/html/boost_asio/example/cpp03/http/server/

I modified the server class so that I could start the server, end the server and restart it.

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

You can see I moved the resolving and listening from the constructor to a start_server function. I then moved the contents of handle_stop to end_server.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

This works if I just start the server and end it once like this (Using a thread to end after 30 seconds just to test):

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

But if I try to restart the server after it has been stopped, io_context->run(); returns immediately, I thought that it should block as async_accept was called on the acceptor again:

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

The server works for the first 30 seconds and then stops like expected, but then when started again, run returns immediately and it doesn’t start again.

>Solution :

Per the boost documentation:

Subsequent calls to run(), run_one(), poll() or poll_one() will return immediately unless there is a prior call to restart().

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading