使用websocketpp的C++ WebSocket客户端无法接收消息求助
问题排查与修复
常见导致消息回调不触发的原因及修复
1. 消息回调签名不匹配
websocketpp的客户端消息回调必须严格符合指定签名,错误的参数类型或命名空间会导致框架无法正确触发回调。正确签名示例:
void on_message(websocketpp::connection_hdl hdl, client::message_ptr msg)
确保你的回调函数参数类型、命名空间归属完全一致。
2. 未启动事件循环或程序过早退出
websocketpp依赖底层IO服务(如asio::io_service)处理网络事件,若连接成功后未保持IO服务运行,程序会直接退出,无法接收后续消息。
修复方式:在连接成功后调用客户端的run()方法,让事件循环持续运行:
// 连接启动后保持程序运行以处理网络事件 client.run();
3. 未发送消息触发回声服务
wss://echo.websocket.org是回声服务,只有客户端发送消息后,服务才会返回对应回声。若客户端仅连接而未发送消息,自然不会触发消息接收回调。
在连接成功的回调中添加消息发送逻辑:
void on_open(websocketpp::connection_hdl hdl) { std::cout << "连接成功" << std::endl; // 发送测试消息触发回声 client* c = static_cast<client*>(hdl.lock()->get_user_data()); c->send(hdl, "Hello WebSocket!", websocketpp::frame::opcode::text); }
修正后的完整示例代码
#include <websocketpp/client.hpp> #include <websocketpp/config/asio_client.hpp> #include <iostream> typedef websocketpp::client<websocketpp::config::asio_tls_client> client; using websocketpp::lib::placeholders::_1; using websocketpp::lib::placeholders::_2; using websocketpp::lib::bind; // TLS初始化(测试环境禁用证书验证,生产环境需启用) bool on_tls_init(websocketpp::connection_hdl hdl, client::connection_ptr conn) { conn->set_tls_init_handler([](websocketpp::connection_hdl) { auto ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::tlsv12_client); try { ctx->set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3 | boost::asio::ssl::context::single_dh_use); } catch (std::exception& e) { std::cout << "TLS初始化失败: " << e.what() << std::endl; } return ctx; }); return true; } void on_open(websocketpp::connection_hdl hdl) { std::cout << "连接成功" << std::endl; // 从连接句柄获取客户端实例,发送测试消息 client* c = static_cast<client*>(hdl.lock()->get_user_data()); c->send(hdl, "Hello WebSocket Echo!", websocketpp::frame::opcode::text); } void on_message(websocketpp::connection_hdl hdl, client::message_ptr msg) { std::cout << "收到消息: " << msg->get_payload() << std::endl; // 可选:收到消息后关闭连接 // client* c = static_cast<client*>(hdl.lock()->get_user_data()); // c->close(hdl, websocketpp::close::status::normal, "收到回声"); } int main() { client c; try { // 初始化ASIO服务 c.init_asio(); // 设置用户数据,方便回调中获取客户端实例 c.set_user_data(&c); // 注册回调 c.set_open_handler(bind(&on_open, ::_1)); c.set_message_handler(bind(&on_message, ::_1, ::_2)); c.set_tls_init_handler(bind(&on_tls_init, ::_1, ::_2)); // 关闭冗余日志(可选) c.set_access_channels(websocketpp::log::alevel::none); c.set_error_channels(websocketpp::log::elevel::none); // 创建连接 websocketpp::lib::error_code ec; client::connection_ptr conn = c.get_connection("wss://echo.websocket.org", ec); if (ec) { std::cout << "连接创建失败: " << ec.message() << std::endl; return 1; } // 启动连接并运行事件循环 c.connect(conn); c.run(); } catch (websocketpp::exception const& e) { std::cout << "异常: " << e.what() << std::endl; } return 0; }
编译命令(依赖Boost和OpenSSL)
g++ -std=c++11 client.cpp -o client -lboost_system -lssl -lcrypto
更简便的WebSocket客户端实现方式
如果觉得websocketpp配置繁琐,可选择以下现代C++库:
1. Boost.Beast
Boost官方的WebSocket/HTTP组件,API符合现代C++风格,支持同步/异步模式,配置简洁。
同步客户端示例:
#include <boost/beast.hpp> #include <boost/asio.hpp> #include <iostream> #include <string> namespace beast = boost::beast; namespace websocket = beast::websocket; namespace net = boost::asio; using tcp = boost::asio::ip::tcp; int main() { try { net::io_context ioc; // 解析服务器地址 tcp::resolver resolver(ioc); auto const results = resolver.resolve("echo.websocket.org", "443"); // 建立带TLS的WebSocket连接 websocket::stream<beast::ssl_stream<tcp::socket>> ws(ioc); ws.next_layer().set_verify_mode(boost::asio::ssl::verify_none); // 测试用,生产需验证证书 ws.next_layer().handshake(boost::asio::ssl::stream_base::client); ws.handshake("echo.websocket.org", "/"); // 发送消息 std::string msg = "Hello Boost.Beast!"; ws.write(net::buffer(msg)); // 接收回声 beast::flat_buffer buffer; ws.read(buffer); std::cout << "收到消息: " << beast::make_printable(buffer.data()) << std::endl; // 关闭连接 ws.close(websocket::close_code::normal); } catch (std::exception const& e) { std::cout << "异常: " << e.what() << std::endl; return 1; } return 0; }
编译命令:
g++ -std=c++17 beast_client.cpp -o beast_client -lboost_system -lssl -lcrypto
2. cpprestsdk (Casablanca)
微软开源跨平台网络库,WebSocket客户端API简洁,支持异步操作。
示例代码:
#include <cpprest/ws_client.h> #include <iostream> using namespace web; using namespace web::websockets::client; int main() { websocket_client client; // 连接服务 client.connect(U("wss://echo.websocket.org")).wait(); // 发送消息 websocket_outgoing_message msg; msg.set_utf8_message(U("Hello cpprestsdk!")); client.send(msg).wait(); // 接收回声并打印 client.receive().then([](websocket_incoming_message msg) { return msg.extract_string(); }).then([](std::string body) { std::cout << "收到消息: " << body << std::endl; }).wait(); // 关闭连接 client.close().wait(); return 0; }
编译命令(需预先安装cpprestsdk):
g++ -std=c++11 cpprest_client.cpp -o cpprest_client -lcpprest -lboost_system -lssl -lcrypto
内容的提问来源于stack exchange,提问作者rampatowl
相关产品推荐
相关产品推荐

