WebSocket на C++: real-time приложения от А до Я
В современном мире веб-технологий пользователи ожидают мгновенной реакции от приложений. Традиционный HTTP-протокол, работающий по схеме "запрос-ответ", плохо подходит для задач, требующих постоянного обновления данных: онлайн-чатов, биржевых котировок, многопользовательских игр и систем мониторинга. Именно здесь на помощь приходит WebSocket — протокол, обеспечивающий постоянное двунаправленное соединение между клиентом и сервером.
В этой статье мы разберем, как создавать real-time приложения на C++ с использованием WebSocket. Вы узнаете о библиотеках, архитектуре и напишете свой первый рабочий код.
Что такое WebSocket и зачем он нужен в C++?
WebSocket — это протокол, который устанавливает постоянное TCP-соединение между клиентом и сервером. После рукопожатия (handshake) данные могут передаваться в обе стороны без необходимости повторных HTTP-запросов. Это кардинально снижает задержки и нагрузку на сеть.
C++ — идеальный язык для high-performance real-time систем. Он дает полный контроль над памятью, потоками и сетевыми операциями. В сочетании с WebSocket вы получаете:
- Минимальную задержку — данные доставляются за миллисекунды.
- Высокую пропускную способность — тысячи одновременных подключений.
- Энергоэффективность — низкое потребление ресурсов сервера.
Примеры использования: биржевые терминалы, онлайн-игры (например, шахматы в реальном времени), системы уведомлений, IoT-устройства и даже стриминг данных с датчиков.
Выбор библиотеки: Boost.Beast vs uWebSockets
На C++ есть несколько популярных библиотек для работы с WebSocket. Мы рассмотрим две основные:
Boost.Beast
Это часть экосистемы Boost, написанная на современном C++11/14/17. Beast предоставляет низкоуровневый контроль над WebSocket и HTTP. Он асинхронный, основан на Boost.Asio и идеально подходит для серьезных проектов.
uWebSockets (µWebSockets)
Легковесная и сверхбыстрая библиотека. Написана на C++17, ориентирована на максимальную производительность. Идеальна для микросервисов и простых real-time приложений.
Для этого руководства мы выберем Boost.Beast, так как он более гибкий и лучше документирован для образовательных целей.
Пишем WebSocket сервер на C++ с Boost.Beast
Давайте создадим простой эхо-сервер, который принимает сообщения от клиента и отправляет их обратно. Это база для любого real-time приложения.
Для начала установите Boost.Beast и Asio. В большинстве Linux-дистрибутивов это делается через пакетный менеджер:
sudo apt install libboost-all-dev
Теперь код сервера:
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <iostream>
#include <string>
#include <thread>
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::endpoint(tcp::v4(), 8080)};
std::cout << "WebSocket server started on ws://localhost:8080" << std::endl;
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 0;
}
Объяснение:
- Мы создаем TCP-акцептор на порту 8080.
- Для каждого нового соединения запускаем отдельный поток (
std::thread). - Внутри функции
do_sessionвыполняем WebSocket-рукопожатие (ws.accept()). - Далее в бесконечном цикле читаем сообщения и отправляем их обратно (эхо).
Скомпилируйте с флагом -lpthread и запустите:
g++ -std=c++17 -O2 -pthread server.cpp -o server
./server
Создаем WebSocket клиент на C++
Теперь напишем клиент, который подключается к нашему серверу и отправляет сообщение.
#include <boost/beast/core.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <iostream>
#include <string>
namespace beast = boost::beast;
namespace websocket = beast::websocket;
namespace net = boost::asio;
using tcp = net::ip::tcp;
int main() {
try {
net::io_context ioc;
tcp::resolver resolver{ioc};
websocket::stream<tcp::socket> ws{ioc};
auto const results = resolver.resolve("127.0.0.1", "8080");
net::connect(ws.next_layer(), results.begin(), results.end());
ws.handshake("127.0.0.1", "/");
std::string message = "Hello, WebSocket!";
ws.write(net::buffer(message));
beast::flat_buffer buffer;
ws.read(buffer);
std::cout << "