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

为何WebSocket++客户端发送距离数据失败?此前同代码可正常运行

问题分析与解决方案

核心问题

  1. IO线程被阻塞:on_message回调运行在WebSocket++的IO服务线程中,收到"Start"信号后,摄像头循环直接在该线程内执行,导致IO服务无法处理后续的WebSocket消息收发、心跳等操作——这是距离数据无法送达的根本原因。而"Hello"在连接建立时发送(此时未进入阻塞循环)、"Bye, server!"在收到"Stop"时发送(若"Stop"在阻塞前收到或循环被中断),所以能正常传输。
  2. 线程不安全的消息发送:通过独立线程调用client::send,但WebSocket++的客户端方法并非线程安全,直接跨线程调用会引发未定义行为。
  3. 潜在的类型错误:若distance是数值类型(如float/int),未转换为std::string就传入发送函数会导致编译错误或无效消息。

修复方案

1. 避免阻塞IO线程

将摄像头循环移到独立线程中执行,释放IO服务线程处理WebSocket相关操作。

2. 线程安全的消息发送

使用client::post方法将发送任务提交到IO服务线程执行,保证线程安全。

3. 确保消息格式正确

将数值类型的distance转换为std::string后再发送。

修改后的关键代码

// 替换原有的async_send_handler和async_send_message
void async_send_message(client* c, websocketpp::connection_hdl hdl, const std::string& message) {
    // 将发送任务提交到IO服务线程执行
    c->post([c, hdl, message]() {
        try {
            // 检查连接句柄是否有效
            auto con = c->get_con_from_hdl(hdl);
            if (!con) {
                c->get_alog().write(websocketpp::log::alevel::app, "Invalid connection handle");
                return;
            }
            c->send(hdl, message, websocketpp::frame::opcode::text);
            c->get_alog().write(websocketpp::log::alevel::app, "Sent Message: " + message);
        } catch (...) {
            c->get_alog().write(websocketpp::log::alevel::app, "Send Failed");
        }
    });
}

// 修改on_message中的Start分支
void on_message(client* c, websocketpp::connection_hdl hdl, message_ptr msg) {
    c->get_alog().write(websocketpp::log::alevel::app, "Received Reply: " + msg->get_payload());

    if (msg->get_payload() == "Stop") {
        async_send_message(c, hdl, "Bye, server!");
        std::this_thread::sleep_for(std::chrono::seconds(1));
        c->close(hdl, websocketpp::close::status::normal, "");
    }

    if (msg->get_payload() == "Start") {
        // 启动独立线程处理摄像头循环,不阻塞IO线程
        boost::thread([c, hdl]() {
            // 初始化摄像头管道(原Camera Pipeline Code)
            rs2::pipeline pipe;
            rs2::config cfg;
            // ... 你的摄像头配置代码 ...

            rs2::pipeline_profile profile = pipe.start(cfg);

            while (true) {
                // 获取帧数据并计算距离
                rs2::frameset frames = pipe.wait_for_frames();
                rs2::depth_frame depth = frames.get_depth_frame();
                float calculated_distance = depth.get_distance(320, 240); // 示例:获取中心像素距离
                std::string distance_str = std::to_string(calculated_distance); // 转换为字符串

                // 发送距离数据
                try {
                    async_send_message(c, hdl, distance_str);
                } catch (const std::exception& e) {
                    c->get_alog().write(websocketpp::log::alevel::app, "Send exception");
                    std::cout << "Exception occurred: " << e.what() << std::endl;
                }
                c->get_alog().write(websocketpp::log::alevel::app, "Sent Message: " + distance_str);

                // 可选:添加延时,避免发送频率过高
                std::this_thread::sleep_for(std::chrono::milliseconds(100));
            }
        }).detach();
    }
}

额外注意事项

  • 若需要终止摄像头线程,可以添加一个线程安全的标志变量,在收到"Stop"信号时设置标志,让循环退出。
  • 始终检查connection_hdl的有效性:由于connection_hdl是弱引用,发送前通过get_con_from_hdl确认连接是否仍存在,避免无效操作。

内容的提问来源于stack exchange,提问作者TheLBL

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 11:57:02