0

0

c++如何实现websocket通信_c++ websocketpp库配置与服务端逻辑【实战】

穿越時空

穿越時空

发布时间:2026-01-07 17:11:10

|

124人浏览过

|

来源于php中文网

原创

WebSocket在C++中无标准库支持,websocketpp是主流纯头文件方案;需正确配置Boost.Asio依赖、禁用permessage-deflate压缩、处理连接生命周期事件,并注意线程安全与广播机制。

c++如何实现websocket通信_c++ websocketpp库配置与服务端逻辑【实战】

WebSocket 在 C++ 中没有标准库支持,websocketpp 是目前最成熟、免依赖 Boost.Asio(可选)、纯头文件的主流方案。它不绑定具体网络后端,但默认推荐搭配 Boost.Asio 使用;若想零依赖,也可用 standalone Asio 替代,但需手动处理 TLS 和底层 socket 细节。

如何配置 websocketpp(CMake + Boost.Asio)

常见错误是只包含头文件却未链接 Boost.System 或漏定义宏,导致编译失败或运行时崩溃。

  • 确保安装了 boost(≥1.65),至少包含 boost_systemboost_thread
  • CMakeLists.txt 中必须添加:
    find_package(Boost REQUIRED COMPONENTS system thread)
    target_link_libraries(your_target PRIVATE Boost::system Boost::thread)
  • 在包含 websocketpp/config/asio_no_tls.hpp 前,定义 BOOST_ASIO_STANDALONE 会导致冲突,应避免;正确做法是直接使用 asio.hppasio_no_tls.hpp,并确保 BOOST_SYSTEM_DYN_LINK 宏与链接方式一致
  • 若用 MinGW 编译,需额外加 -DBOOST_THREAD_USE_LIB 防止 undefined reference to `boost::system::generic_category()`

写一个最小可用的服务端(echo server)

核心是继承 websocketpp::server 模板,并注册消息回调。注意:所有 handler 回调都运行在 IO 线程中,不可阻塞;如需耗时操作,必须 offload 到线程池。

  • 使用 websocketpp::config::asio(带 TLS 支持)或 asio_no_tls(纯 HTTP 协议)
  • set_message_handler 的 lambda 参数是 connection_hdlmessage_ptr,后者需用 get_payload() 提取字符串
  • 发送响应必须用 send(hdl, payload, opcode),其中 opcode 通常为 websocketpp::frame::opcode::text
  • 服务端启动前必须调用 listen()start_accept(),否则不会接收连接
#include 
#include 
#include 

typedef websocketpp::server server;

立即学习C++免费学习笔记(深入)”;

GPTAgent
GPTAgent

一个无代码创建AI应用程序的工具

下载

int main() { server s; s.init_asio(); s.set_access_channels(websocketpp::log::alevel::all); s.clear_access_channels(websocketpp::log::alevel::frame_payload);

s.set_message_handler([](server* s, websocketpp::connection_hdl hdl, server::message_ptr msg) {
    std::string payload = msg->get_payload();
    s->send(hdl, "echo: " + payload, websocketpp::frame::opcode::text);
});

s.listen("0.0.0.0", "9002");
s.start_accept();
s.run();

}

如何处理连接生命周期与错误(on_open / on_close / on_fail)

实际项目中,仅处理消息远远不够。连接建立、异常中断、超时断开等事件必须显式捕获,否则会内存泄漏或状态错乱。

  • on_open 中建议用 s->get_con_from_hdl(hdl) 获取连接对象,保存其 ID 或 IP 地址用于后续管理
  • on_closeon_fail 都需检查 ec(error_code):例如 websocketpp::close::status::going_away 表示正常关闭,而 asio::error::operation_aborted 多见于服务停止时的主动 cancel
  • 不要在 on_fail 中调用 s->close(hdl, ...) —— 此时连接已失效,会触发二次异常
  • 若启用了 ping/pong(set_pong_timeout),超时未响应会自动触发 on_close,无需手动心跳检测

为什么 send() 后客户端收不到消息?

最常被忽略的是:websocketpp 默认启用 permessage-deflate 压缩(即使没协商成功),而某些 JS 客户端(如浏览器原生 WebSocket)不支持该扩展,导致静默丢包。

  • 解决方法:初始化 server 后立即禁用压缩:
    s.clear_access_channels(websocketpp::log::alevel::decompress_failure);
    s.set_permessage_deflate_enabled(false);
  • 另一个原因是异步发送未等待完成:若在 on_message 中连续调用多次 send(),且未检查返回的 future(仅当启用 asio::io_context::strand 时才返回),可能因缓冲区满而丢弃后续消息
  • 调试技巧:启用 websocketpp::log::alevel::frame_header 查看每帧 opcode 和 length,确认是否真的发出了数据

真正麻烦的不是写通 echo,而是连接数增长后如何安全地广播、如何跨线程管理 connection_hdl、如何配合现有 event loop(比如 Qt 或 libuv)。这些地方 websocketpp 不提供银弹,得靠你自己加锁、引用计数或消息队列 —— 它只是个协议,不是应用框架。

相关专题

更多
视频后缀名都有哪些
视频后缀名都有哪些

视频后缀名都有avi、mpg、mpeg、rm、rmvb、flv、wmv、mov、mkv、ASF、M1V、M2V、MPE、QT、VOB、RA、RMJ、RMS、RAM、等等。更多关于视频后缀名的相关知识,详情请看本专题下面的文章,php中文网欢迎大家前来学习。

3394

2023.10.31

C++ Qt图形开发
C++ Qt图形开发

本专题专注于 C++ Qt框架在图形界面开发中的应用,系统讲解窗口设计、信号与槽机制、界面布局、事件处理、数据库连接与跨平台打包等核心技能,通过多个桌面应用项目实战,帮助学员快速掌握 Qt 框架并独立完成跨平台GUI软件的开发。

68

2025.08.15

C++ 图形界面开发基础(Qt方向)
C++ 图形界面开发基础(Qt方向)

本专题系统讲解 使用 C++ 与 Qt 进行图形界面(GUI)开发的核心技能,内容涵盖 Qt 项目结构、窗口组件、信号与槽机制、事件处理、布局管理、资源管理,以及跨平台编译与打包流程。通过多个小型桌面应用实战案例,帮助学习者掌握从界面设计到功能实现的完整 GUI 开发能力。

52

2025.12.05

scripterror怎么解决
scripterror怎么解决

scripterror的解决办法有检查语法、文件路径、检查网络连接、浏览器兼容性、使用try-catch语句、使用开发者工具进行调试、更新浏览器和JavaScript库或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

186

2023.10.18

500error怎么解决
500error怎么解决

500error的解决办法有检查服务器日志、检查代码、检查服务器配置、更新软件版本、重新启动服务、调试代码和寻求帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

271

2023.10.25

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

253

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

206

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1463

2023.10.24

java学习网站推荐汇总
java学习网站推荐汇总

本专题整合了java学习网站相关内容,阅读专题下面的文章了解更多详细内容。

6

2026.01.08

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 8.2万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 3.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号