Что такое Boost.Asio и как он используется
Что проверяют
Знаете ли вы модель асинхронного ввода-вывода и умеете ли построить сетевой сервис, который держит тысячи соединений на одном или нескольких рабочих потоках, а не выделяет поток на каждого клиента. Дальше обычно идут уточнения про время жизни объектов и про многопоточность: библиотека даёт механизм, а корректность владения буферами и сокетами остаётся на вас.
Как отвечать
Boost.Asio это библиотека C++ для асинхронного ввода-вывода: сокеты TCP и UDP, таймеры, сигналы, последовательные порты, разрешение имён. Центр всего это io_context, очередь готовых операций; потоки, вызвавшие run(), исполняют обработчики завершения. Внутри используются epoll, kqueue или IOCP, поэтому одна нить обслуживает множество дескрипторов.
Операция запускается функцией с префиксом async_ и получает токен завершения: лямбду-колбэк, use_future или use_awaitable для корутин C++20. Вызов возвращает управление сразу, обработчик выполнится позже, в потоке, который крутит io_context.
boost::asio::io_context io;
tcp::acceptor acceptor(io, tcp::endpoint(tcp::v4(), 9000));
acceptor.async_accept([](boost::system::error_code ec, tcp::socket s) {
if (!ec) std::make_shared<Session>(std::move(s))->start();
});
io.run();Сессия наследуется от enable_shared_from_this и захватывает shared_from_this() в каждый обработчик: пока операция в полёте, объект жив. Ошибки приходят кодом в обработчик, а не исключением.
Где спотыкаются
Показывают синхронный код (accept и read_some в цикле) и называют его асинхронным. Такой сервер обслуживает клиентов строго по очереди, второе соединение ждёт, пока закончится первое.
Забывают вызвать run() или вызывают его до постановки первой операции. Очередь пуста, run() выходит немедленно, программа завершается молча, будто отправки и не было.
Передают в буфер локальную переменную или объект, который умирает раньше обработчика. Асинхронная операция пишет по указателю на освобождённую память, и падение приходит совсем не там, где ошибка. Отдельная история это несколько потоков на одном io_context: обработчики одного сокета начинают выполняться параллельно, и без strand состояние сессии рвётся.