讲师中心 微信公众号

工具推荐

视频效率加速
剧云
剧云

中文短剧剧本制作平台

Seko
Seko

AI短剧一键生成成片

Laper
Laper

剧本策划到成片协作

updream

一键生成高质量推广成片

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

梦墨同学_5719

梦墨同学_5719

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

|

517人浏览过

|

来源于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.Beast 的 websocket::stream 不是线程安全的,每个连接必须绑定唯一 io_context::strand,否则并发 write 可能 crash
  • 二者都不建议在 onMessage 回调里做阻塞 IO(如读文件、查数据库),必须异步调度到 worker 线程池,否则整个事件循环卡住

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

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

实操建议:

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

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • 启用心跳:在 App().ws(...) 配置里加 .pingInterval(10000).maxBacklog(1024),并实现 onPing 和 onPong,配合 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),并在 onClose 或 onDisconnection 里 delete static_cast<mysession>(ws->getUserData())</mysession>

Boost.Beast 的 async_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::stream 的 async_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?

uWebSockets 的 App().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::ConcurrentQueue 或 boost::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工具

更多
小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

SoundView
SoundView Hot

SoundView是一款面向跨境电商的视频翻译、配音和本地化 AI 创作平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

音述AI
音述AI Hot

一款AI音频处理工具,主要用于音述AI是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区,适合需要提升相关任务效率的用户。

SkildArt
SkildArt Hot

SkildArt是一款AI文本写作工具,一站式 AI 视觉创作平台。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

相关专题

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

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

1069

2023.10.18

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

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

3520

2023.10.25

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

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

7007

2023.07.18

堆和栈区别
堆和栈区别

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

2868

2023.08.10

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

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

4858

2023.08.10

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

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

1369

2025.12.24

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

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

463

2026.01.21

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

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

599

2026.01.21

Go-Zero API开发使用教程
Go-Zero API开发使用教程

本专题聚焦Go-Zero的API开发,拆解.api描述文件的语法结构、路由与分组定义、参数绑定与校验规则,说明统一响应体、JWT鉴权、跨域与接口文档生成的落地方式,并给出网关聚合与接口测试的实践建议。

20

2026.11.12

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WebSocket手册
WebSocket手册

共0课时 | 0人学习

Webman中文手册
Webman中文手册

共0课时 | 0人学习

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

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn