WebSocket библиотеки C++: обзор и примеры использования

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

WebSocket библиотеки для C++: полное руководство

WebSocket — это протокол, обеспечивающий полнодуплексную связь между клиентом и сервером поверх одного TCP-соединения. В отличие от HTTP, WebSocket позволяет серверу отправлять данные клиенту без предварительного запроса, что делает его идеальным для чатов, игр, биржевых котировок и других real-time приложений. В экосистеме C++ существует несколько зрелых библиотек, реализующих этот протокол. В этой статье мы рассмотрим три наиболее популярные: Boost.Beast, uWebSockets и libwebsockets.

1. Boost.Beast (рекомендуемый)

Boost.Beast — это библиотека на основе Boost.Asio, предоставляющая HTTP и WebSocket протоколы. Она является частью официального дистрибутива Boost (начиная с версии 1.66). Главные преимущества: строгая типизация, полная поддержка стандарта RFC 6455, интеграция с Asio для асинхронной работы.

Основные возможности:

  • Синхронные и асинхронные WebSocket клиенты/серверы
  • Поддержка фреймов, пингов/понгов, закрытия соединения
  • Работа поверх TLS (через Boost.Asio SSL)
  • Кроссплатформенность (Linux, Windows, macOS)

Пример WebSocket сервера (асинхронный):

#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdlib>
#include <functional>
#include <iostream>
#include <string>

namespace beast = boost::beast;
namespace websocket = beast::websocket;
namespace net = boost::asio;
using tcp = net::ip::tcp;

void do_session(tcp::socket& socket) {
    try {
        websocket::stream<tcp::socket> ws{std::move(socket)};
        ws.accept();

        for(;;) {
            beast::flat_buffer buffer;
            ws.read(buffer);
            auto msg = beast::buffers_to_string(buffer.data());
            std::cout << "Received: " << msg << std::endl;

            // Эхо-ответ
            ws.text(ws.got_text());
            ws.write(buffer.data());
        }
    } catch(beast::system_error const& se) {
        if(se.code() != websocket::error::closed) {
            std::cerr << "Error: " << se.code().message() << std::endl;
        }
    }
}

int main() {
    try {
        net::io_context ioc{1};
        tcp::acceptor acceptor{ioc, {tcp::v4(), 8080}};

        for(;;) {
            tcp::socket socket{ioc};
            acceptor.accept(socket);
            std::thread{std::bind(&do_session, std::move(socket))}.detach();
        }
    } catch(std::exception const& e) {
        std::cerr << "Error: " << e.what() << std::endl;
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

2. uWebSockets (uWS)

uWebSockets — это высокопроизводительная библиотека, ориентированная на максимальную скорость и минимальное потребление памяти. Она написана на C++17 и использует собственный event loop (не Boost.Asio). Отлично подходит для микросервисов и приложений с тысячами одновременных подключений.

Ключевые особенности:

  • Очень низкая задержка (~2-3 микросекунды на сообщение)
  • Поддержка WebSocket, HTTP и SSE (Server-Sent Events)
  • Встроенная поддержка TLS (через OpenSSL или BoringSSL)
  • Не требует внешних зависимостей (кроме OpenSSL для TLS)

Пример простого WebSocket сервера:

#include "App.h"

int main() {
    uWS::App().ws<int>("/*", {
        .open = [](auto* ws) {
            std::cout << "Client connected" << std::endl;
            ws->send("Welcome!", uWS::OpCode::TEXT);
        },
        .message = [](auto* ws, std::string_view message, uWS::OpCode opCode) {
            std::cout << "Received: " << message << std::endl;
            ws->send(message, opCode); // эхо
        },
        .close = [](auto* ws, int code, std::string_view message) {
            std::cout << "Client disconnected" << std::endl;
        }
    }).listen(9001, [](auto* listenSocket) {
        if (listenSocket) {
            std::cout << "Listening on port 9001" << std::endl;
        }
    }).run();

    return 0;
}

Рекомендаций