C++ 的 WebSocket 库:完整指南
WebSocket 是一种协议,通过单个 TCP 连接在客户端和服务器之间提供全双工通信。与 HTTP 不同,WebSocket 允许服务器在无需预先请求的情况下向客户端发送数据,使其成为聊天、游戏、股票行情和其他实时应用的理想选择。在 C++ 生态系统中,有多个成熟的库实现了此协议。在本文中,我们将介绍三个最流行的库:Boost.Beast、uWebSockets 和 libwebsockets。
1. Boost.Beast(推荐)
Boost.Beast 是一个基于 Boost.Asio 的库,提供 HTTP 和 WebSocket 协议。它是官方 Boost 发行版的一部分(从 1.66 版本开始)。主要优点包括:强类型、完全支持 RFC 6455 标准、与 Asio 集成以实现异步操作。
主要功能:
- 同步和异步 WebSocket 客户端/服务器
- 支持帧、ping/pong、连接关闭
- 通过 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 编写,并拥有自己的事件循环(非 Boost.Asio)。非常适合微服务和具有数千个并发连接的应用程序。
主要特点:
- 极低延迟(每条消息约 2-3 微秒)
- 支持 WebSocket、HTTP 和 SSE(服务器发送事件)
- 内置 TLS 支持(通过 OpenSSL 或 BoringSSL)
- 无需外部依赖(TLS 需要 OpenSSL 除外)
简单 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: " <<```