Boost Networking & I/O
Asio: Complete Implementation of the Proactor Model
Asio is the most widely used library in Boost and the de facto standard for C++ network programming.
Proactor vs Reactor
| Model | Notification Timing | Typical Implementation |
|---|---|---|
| Reactor | Ready (readable/writable) | libevent, libuv |
| Proactor | Completion (data read/written) | Asio, IOCP (Windows) |
On Linux, Asio is essentially Reactor + emulated Proactor: epoll reports "readable" → Asio internally performs a non-blocking read() → only after data is ready does it invoke the user's completion handler.
io_context Event Loop
class io_context {
detail::epoll_reactor reactor_; // Linux: epoll
detail::scheduler& scheduler_; // completion handler queue
std::atomic<std::uint64_t> outstanding_work_{0};
public:
std::size_t run(); // blocking run
std::size_t poll(); // non-blocking
void stop(); // force stop
};strand Serialization
auto strand = asio::make_strand(io_ctx);
asio::post(strand, [&data] { data.push_back(1); });
asio::post(strand, [&data] { data.push_back(2); });
// Guarantees strict serialization, no manual locking needed by the userstrand does not bind to a thread — it only guarantees logical serialization. Internally it maintains a separate handler queue and schedules tasks serially by "draining" them.
C++20 Coroutine Integration
asio::awaitable<void> echo_session(tcp::socket socket) {
char data[1024];
while (true) {
std::size_t n = co_await socket.async_read_some(
asio::buffer(data), asio::use_awaitable);
co_await async_write(socket, asio::buffer(data, n),
asio::use_awaitable);
}
}How use_awaitable works: the async operation returns an awaitable<T>, whose operator co_await() returns an awaiter. await_suspend() saves the coroutine frame and initiates the async operation. When the operation completes, coroutine_handle.resume() resumes the coroutine.
Beast: HTTP/WebSocket Protocol Engine
Built on top of Asio, exposing protocol-level abstractions:
beast::http::response<http::string_body> http_get(
const std::string& host, const std::string& target)
{
asio::io_context io_ctx;
tcp::resolver resolver(io_ctx);
beast::tcp_stream stream(io_ctx);
auto results = resolver.resolve(host, "80");
stream.connect(results);
http::request<http::string_body> req{http::verb::get, target, 11};
req.set(http::field::host, host);
http::write(stream, req);
beast::flat_buffer buffer;
http::response<http::string_body> res;
http::read(stream, buffer, res);
return res;
}Beast's design philosophy: zero-overhead abstraction — HTTP header fields use enum lookups instead of string comparisons, and flat_buffer uses a single contiguous memory block to avoid fragmentation.
JSON: DOM and SAX Parsing
Boost.JSON provides two parsing modes:
- DOM mode: Parses the entire input into an in-memory tree structure (
value/object/array) - SAX mode: Event-driven incremental parsing (
basic_parsercallbacks)
boost::json::value jv = boost::json::parse(R"({"name":"Alice","scores":[95,87]})");
std::string name = jv.at("name").as_string();
int first_score = jv.at("scores").at(0).as_int64();Key optimization: monotonic_resource memory pool — all nodes of the JSON tree are allocated in a single memory block, and the entire block is freed at once upon destruction.
URL: RFC 3986 Parsing
Boost.URL implements the full RFC 3986 URI specification, supporting independent access and modification of authority, path, query, and fragment components.