0

0

C++如何构建基于WebSocket的高性能实时通信服务器?(网络并发)

穿越時空

穿越時空

发布时间:2026-03-01 13:35:39

|

357人浏览过

|

来源于php中文网

原创

高并发、低延迟场景优先选uwebsockets;需深度定制协议或已有boost生态则选boost.beast。前者基于libusockets,零拷贝无锁,单核扛10w+连接;后者依赖asio,内存管理较重,易因shared_ptr分配卡堆。

c++如何构建基于websocket的高性能实时通信服务器?(网络并发)

WebSocket 服务器选 uWebSockets 还是 Boost.Beast

直接说结论:高并发、低延迟场景优先选 uWebSockets;需要深度定制协议或已有 Boost 生态的项目,再考虑 Boost.Beast。前者基于 libusockets,零拷贝、无锁事件循环,单核轻松扛 10w+ 连接;后者依赖 ASIO,对象生命周期和内存管理稍重,压测时容易因 std::shared_ptr 频繁分配卡在堆上。

常见错误现象:Boost.Beast 里忘记调用 stream.set_option(websocket::stream_base::timeout::suggested(beast::role_type::server)),导致空闲连接不自动断开,连接数缓慢泄漏;uWebSockets 中误用 res->end() 替代 res->close() 关闭 WebSocket,结果触发 HTTP 断连逻辑而非 WS 正常关闭。

  • uWebSockets 编译必须开 -DUSING_UWS,否则 uWS::App() 构造失败且报错极隐晦(只提示 undefined reference to uWS::App::App()
  • Boost.Beastwebsocket::stream 不是线程安全的,每个连接必须绑定唯一 io_context::strand,否则并发 write 可能 crash
  • 二者都不建议在 onMessage 回调里做阻塞 IO(如读文件、查数据库),必须异步调度到 worker 线程池,否则整个事件循环卡住

如何避免 uWebSockets 的内存泄漏和连接堆积?

根本原因不是代码写错,而是默认行为太“省事”:它不自动清理断连残留的 WebSocket 对象,尤其当客户端异常掉线(比如 kill -9 浏览器进程),服务端收不到 close 帧,onClose 根本不触发。

实操建议:

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

飞书知识问答
飞书知识问答

飞书平台推出的AI知识库管理和智能搜索工具

下载
  • 启用心跳:在 App().ws(...) 配置里加 .pingInterval(10000).maxBacklog(1024),并实现 onPingonPong,配合 ws->getBufferedAmount() > 1024 * 1024 主动 ws->close()
  • 给每个 ws 绑定一个 std::chrono::steady_clock::time_point 记录最后活跃时间,在 onMessage/onPing 里更新,在定时器中扫描超时(比如 60s 无活动)的连接并 ws->close()
  • 不要在 onConnection 里 new 对象存到全局 map,改用 ws->setUserData(new MySession),并在 onCloseonDisconnectiondelete static_cast<mysession>(ws->getUserData())</mysession>

Boost.Beastasync_read 为什么总卡住不回调?

不是网络问题,大概率是 flat_buffer 没预分配空间,或者 read 调用时机不对。Beast 默认 buffer 初始容量为 0,第一次 async_read 会先分配内存再 copy,但若此时远端发的是小包(比如 4 字节 ping),可能因 buffer 不足被截断,后续帧永远等不到完整消息体。

使用场景:适合需要解析混合帧(如 WebSocket + 自定义二进制头)或需与现有 ASIO TCP 服务共用 io_context 的情况。

  • 声明 buffer 时务必指定初始大小:beast::flat_buffer buffer{4096},而不是 beast::flat_buffer buffer
  • websocket::streamasync_read 必须在前一次回调完成后再发起,不能在 on_message 里立刻再 call 一次 —— 否则会触发 boost::asio::error::operation_not_supported
  • 如果用了 stream.binary(true),但客户端发的是文本帧,async_read 会静默失败(不报错也不回调),需检查 ws.got_text() / ws.got_binary()

并发模型:用 std::thread 手搓线程池还是交给 uWebSockets 自带的 run

uWebSocketsApp().run() 内部已封装多线程 epoll/kqueue 循环,调用它就等于启动了最优并发模型;自己额外开 std::thread 跑多个 App 实例反而降低性能 —— 因为每个实例都独占 fd 和事件队列,TCP accept 会竞争,连接分布不均。

真正要做的,是把 CPU 密集型任务(如 protobuf 解析、加密验签)从主线程挪出去:

  • std::async(std::launch::async, []{ /* heavy work */ }) 包裹耗时操作,完成后用 ws->send() 推送结果(注意:ws 对象不能跨线程访问,必须用 ws->getNativeHandle() 或自定义 ID 在主线程查表)
  • 避免用 std::queue + std::mutex 做任务分发 —— 锁争用会成为瓶颈;改用 moodycamel::ConcurrentQueueboost::lockfree::queue
  • 如果必须多 io_context,别手写调度,直接用 uWS::Loop::get()->defer([]{ /* main thread only */ }) 把回调安全投递回主事件循环

最易被忽略的一点:所有 WebSocket 库都假设你的业务逻辑不修改 ws 生命周期外的状态。比如在 onMessage 里修改了某个全局 std::map,但没加锁 —— 这不是并发模型的问题,是 C++ 基础错误,调试时表现为随机 core dump,跟网络库无关。

相关文章

数码产品性能查询
数码产品性能查询

该软件包括了市面上所有手机CPU,手机跑分情况,电脑CPU,电脑产品信息等等,方便需要大家查阅数码产品最新情况,了解产品特性,能够进行对比选择最具性价比的商品。

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
scripterror怎么解决
scripterror怎么解决

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

411

2023.10.18

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

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

357

2023.10.25

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

429

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

599

2023.08.10

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

723

2023.08.10

Python 多线程与异步编程实战
Python 多线程与异步编程实战

本专题系统讲解 Python 多线程与异步编程的核心概念与实战技巧,包括 threading 模块基础、线程同步机制、GIL 原理、asyncio 异步任务管理、协程与事件循环、任务调度与异常处理。通过实战示例,帮助学习者掌握 如何构建高性能、多任务并发的 Python 应用。

372

2025.12.24

java多线程相关教程合集
java多线程相关教程合集

本专题整合了java多线程相关教程,阅读专题下面的文章了解更多详细内容。

27

2026.01.21

C++多线程相关合集
C++多线程相关合集

本专题整合了C++多线程相关教程,阅读专题下面的的文章了解更多详细内容。

25

2026.01.21

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

6

2026.02.28

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
swoole入门物联网开发与实战
swoole入门物联网开发与实战

共15课时 | 1.3万人学习

swoole项目实战(第二季)
swoole项目实战(第二季)

共15课时 | 1.3万人学习

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

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