使用Boost Beast实现WebSocket客户端时遇编译错误求助
Boost Beast WebSocket SSL流编译错误排查
问题描述
使用Boost Beast实现C++ WebSocket客户端,连接加密货币交易所WebSocket API处理行情数据时,遇到与Boost Beast和Boost Asio SSL流相关的编译错误,错误触发点在async_teardown逻辑中。
代码片段
#include <array> #include <atomic> #include <thread> #include <cstdlib> #include <string> #include <thread> #include <iostream> #include <sstream> #include <curl/curl.h> #include <shared_mutex> #include <openssl/sha.h> #include <openssl/hmac.h> #include <nlohmann/json.hpp> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> #include <boost/beast.hpp> // ... [Other parts of the code like the OrderBook class] class WebSocketClient { private: using Socket = tcp::socket; using Stream = ssl::stream<Socket>; using WS = websocket::stream<Stream>; net::io_context ioc_; OrderBook &orderBook_; std::string coin_; tcp::resolver resolver_{ioc_}; ssl::context ssl_context_{ssl::context::tlsv12_client}; WS ws_{ioc_, ssl_context_}; boost::beast::flat_buffer buffer_; public: WebSocketClient(OrderBook &orderBook, std::string coin) : orderBook_(orderBook), coin_(std::move(coin)) { ssl_context_.set_default_verify_paths(); ws_.next_layer().set_verify_mode(ssl::verify_peer); ws_.next_layer().set_verify_callback(ssl::rfc2818_verification("stream.binance.com")); } void read() { ws_.async_read( buffer_, [this](boost::system::error_code ec, std::size_t bytes_transferred) { onRead(ec, bytes_transferred); }); } void send(std::string msg) { ws_.write(net::buffer(msg)); } void connectAndSubscribe() { // Resolve the host name and connect to the server auto results = resolver_.resolve("stream.binance.com", "9443"); auto ep = connect(ws_.next_layer().next_layer(), results); auto host_ = "stream.binance.com:" + std::to_string(ep.port()); ws_.next_layer().handshake(Stream::client); // Set a decorator to change the User-Agent of the handshake ws_.set_option(websocket::stream_base::decorator([](websocket::request_type &req) { req.set(http::field::user_agent, std::string(BOOST_BEAST_VERSION_STRING) + " websocket-client"); })); std::string path = "/ws/" + coin_ + "@depth5@100ms"; ws_.handshake(host_, path); std::cout << "Handshake successful." << std::endl; json j_msg = { {"method", "SUBSCRIBE"}, {"params", {coin_ + "@depth5@100ms"}}, {"id", 1}}; std::string msg = j_msg.dump(); // Serialize JSON to string send(msg); std::cout << "Subscription request done!" << std::endl; read(); } void onRead(boost::system::error_code ec, std::size_t bytes_transferred) { if (ec) { std::cerr << "Read error: " << ec.message() << std::endl; return; } // Process the received message std::string message = boost::beast::buffers_to_string(buffer_.data()); buffer_.consume(bytes_transferred); try { json j = json::parse(message); // Process JSON message and update OrderBook std::cout << "Reading request done!" << std::endl; processMessage(j); } catch (const json::exception &e) { std::cerr << "JSON parsing error: " << e.what() << std::endl; } // Continue reading messages read(); } void processMessage(const json &j) { if (j.contains("lastUpdateId") && j.contains("bids") && j.contains("asks")) { int index = 0; for (const auto &bid : j["bids"]) { float price = stof(bid[0].get<string>()); float quantity = stof(bid[1].get<string>()); orderBook_.update(index++, price); orderBook_.update(index++, quantity); } index = 10; // Start index for asks for (const auto &ask : j["asks"]) { float price = stof(ask[0].get<string>()); float quantity = stof(ask[1].get<string>()); orderBook_.update(index++, price); orderBook_.update(index++, quantity); } } } };
错误信息
/usr/local/include/boost/beast/websocket/teardown.hpp:105:5: error: static assertion failed due to requirement 'sizeof(boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>>) == -1': Unknown Socket type in async_teardown.
构建环境
- 构建系统:CMake + Ninja
- 已尝试升级Boost和OpenSSL至最新版本,问题仍存在。
解决思路
1. 显式包含WebSocket SSL支持头文件
编译错误的核心原因是Boost Beast未找到针对SSL流的async_teardown特化实现。需要在代码中显式包含:
#include <boost/beast/websocket/ssl.hpp>
这个头文件提供了SSL流与WebSocket集成所需的teardown逻辑,仅包含<boost/beast.hpp>无法自动引入该特化。
2. 检查命名空间一致性
确保所有Boost Asio/Beast相关类型使用统一的命名空间:
- 若使用别名
namespace net = boost::asio,则所有tcp::socket、ssl::stream等类型需来自net命名空间,修正类型别名定义:
避免因命名空间混乱导致模板特化匹配失败。using Socket = net::ip::tcp::socket; using Stream = net::ssl::stream<Socket>; using WS = boost::beast::websocket::stream<Stream>;
3. 修正WebSocket握手的Host字段
虽然这不是编译错误,但会导致运行时握手失败:当前代码中host_拼接了端口号,WebSocket握手的Host字段仅需主机名(如"stream.binance.com"),无需附加端口,修改为:
auto host_ = "stream.binance.com";
4. 验证Boost版本兼容性
确保使用的Boost版本完全兼容:Beast库对SSL流的支持在Boost 1.70及以上版本才稳定,若升级后仍有问题,可尝试指定Boost版本为1.74+(币安官方示例常用版本)。
内容的提问来源于stack exchange,提问作者Pedro Souto
相关产品推荐
相关产品推荐

