...

/

A Concurrent Server Using Boost.Asio

A Concurrent Server Using Boost.Asio

Learn how to write a concurrent single-threaded TCP server with Boost.Asio, using asynchronous application programming and coroutines.

This section will demonstrate how to write concurrent programs with multiple threads of execution but only use a single OS thread. We are about to implement a rudimentary concurrent single-threaded TCP server that can handle multiple clients. There are no networking capabilities in the C++ standard library but fortunately, Boost.Asio provides us with a platform-agnostic interface for handling socket communication.

Instead of wrapping the callback-based Boost.Asio API, we will demonstrate how to use the boost::asio::awaitable class to show a more realistic example of how asynchronous application programming using coroutines can look. The class template boost::asio::awaitable corresponds to the Task template we created earlier; it’s used as a return type for coroutines that represent asynchronous computations.

Implementing the server

The server is very simple; once a client connects, it starts updating a numeric counter and writes back the value whenever it is updated. This time we will follow the code from top to bottom, starting with the main() function:

Press + to interact
#include <boost/asio.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/use_awaitable.hpp>
using namespace std::chrono;
namespace asio = boost::asio;
using boost::asio::ip::tcp;
asio::awaitable<void> listen(tcp::endpoint endpoint) {
auto acceptor = tcp::acceptor{co_await asio::this_coro::executor};
co_await acceptor.async_listen(endpoint, asio::use_awaitable);
}
int main() {
auto server = [] {
auto endpoint = tcp::endpoint{tcp::v4(), 37259};
co_await listen(endpoint);
};
auto ctx = asio::io_context{};
boost::asio::co_spawn(ctx, server, asio::detached);
ctx.run();
}

The mandatory io_context runs the event processing loop. It’s possible to invoke run() from multiple threads as well if we want our server to execute multiple OS threads. In our case, we only use one thread but with ...