You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 09:58:22