为何WebSocket++客户端发送距离数据失败?此前同代码可正常运行
问题分析与解决方案
核心问题
- IO线程被阻塞:
on_message回调运行在WebSocket++的IO服务线程中,收到"Start"信号后,摄像头循环直接在该线程内执行,导致IO服务无法处理后续的WebSocket消息收发、心跳等操作——这是距离数据无法送达的根本原因。而"Hello"在连接建立时发送(此时未进入阻塞循环)、"Bye, server!"在收到"Stop"时发送(若"Stop"在阻塞前收到或循环被中断),所以能正常传输。 - 线程不安全的消息发送:通过独立线程调用
client::send,但WebSocket++的客户端方法并非线程安全,直接跨线程调用会引发未定义行为。 - 潜在的类型错误:若
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
相关产品推荐
相关产品推荐

