当前位置: 首页 > news >正文

websoket测试工具WsBroadcaster

github地址:https://github.com/johnjiamzhong-project/WsBroadcaster

1776435261955


用 Qt5 实现一个 WebSocket 广播工具:三层架构设计实践

项目简介

WsBroadcaster 是一个基于 Qt5 + C++ 的 WebSocket 调试/广播工具,支持 Server 模式(监听端口、向所有客户端广播)和 Client 模式(连接远端服务器收发消息),带有自定义无边框标题栏和深色主题 UI。


架构设计

项目采用严格的三层结构,层间只允许通过 Qt signal/slot 通信,禁止跨层直接调用:

  UI(MainWindow / TitleBar)↕ signal/slotBridge    (WsBridge)          ← UI 与 Core 的唯一边界↕ signal/slotCore(WsController / MessageRouter / ConnectionMgr)↕Network(WsServer / WsClient)

这个分层的核心价值是可测试性和可替换性——每一层都可以独立 mock,UI 重构不影响 Core,网络库换掉不影响业务逻辑。


核心组件

WsBridge:UI 与 Core 的防腐层

// UI 侧只持有 WsBridge,不知道 WsController/WsServer 的存在

  class WsBridge : public QObject {public slots:void startServer(quint16 port);void sendToAll(const QString &message);void disconnectRemoteClient(QWebSocket *socket);signals:void serverStarted(quint16 port);void remoteClientConnected(QWebSocket *socket, const ConnectionInfo &info);void clientMessageReceived(const QString &message);// ...};

WsBridge 做的事:接收 UI 指令 → 转发给 Core;Core 事件 → 转发给 UI。它本身没有业务逻辑,只是一个类型安全的信号总线。

WsController:模式生命周期管理

  enum class WsMode { None, Server, Client };class WsController : public QObject {WsMode m_mode = WsMode::None;WsServer *m_server = nullptr;WsClient *m_client = nullptr;bool startServer(quint16 port);  // 切换到 Server 模式,自动 teardown 旧实例bool connectClient(const QUrl &url);};

WsController 保证 Server 和 Client 模式互斥,切换时先 teardown() 清理旧实例,再构建新实例。它不做路由,不管连接表,只负责模式切换和基础收发。

ConnectionMgr:连接表的单一真实来源

  struct ConnectionInfo {QString address;quint16 port = 0;QDateTime connectedAt;};class ConnectionMgr : public QObject {QHash<QWebSocket*, ConnectionInfo> m_connections;public:void addConnection(QWebSocket *socket);void removeConnection(QWebSocket *socket);QList<QWebSocket*> connections() const;int count() const;signals:void connectionAdded(QWebSocket *socket, const ConnectionInfo &info);void connectionRemoved(QWebSocket *socket, const ConnectionInfo &info);};

只要涉及"当前有哪些客户端连接",查 ConnectionMgr,不查其他地方。这是 Single Source of Truth 原则的具体落地。

MessageRouter:无状态消息分发

  class MessageRouter : public QObject {public slots:void broadcastAll(const QString &message);  // 广播给所有客户端void unicast(QWebSocket *socket, const QString &message);void clientSend(const QString &message);signals:void doSendToAll(const QString &message);void doSendTo(QWebSocket *socket, const QString &message);void doClientSend(const QString &message);};

MessageRouter 不持有任何 socket 对象,通过发出信号触发实际网络发送。无状态设计让它可以独立单测。


自定义无边框标题栏

为了配合深色主题,移除了系统原生标题栏,自己实现拖拽、最大化、双击还原:

  class TitleBar : public QWidget {void mousePressEvent(QMouseEvent *event) override;void mouseMoveEvent(QMouseEvent *event) override;void mouseDoubleClickEvent(QMouseEvent *event) override;// nativeEvent 处理 WM_NCHITTEST 保留系统窗口吸附/Aero Snap 行为};

关键点:Qt::FramelessWindowHint 去掉边框后,需要在 MainWindow::nativeEvent 里响应 WM_NCHITTEST,才能保留 Windows 的窗口吸附、贴边等原生行为。


构建配置

  cmake -B build -G Ninja \-DCMAKE_BUILD_TYPE=Debug \-DCMAKE_PREFIX_PATH="E:/Qt/Qt5.14.2/5.14.2/msvc2017_64"cmake --build build

注意点:

  • MSVC + 中文注释:CMakeLists 里必须加 /utf-8 编译选项,否则会出现级联 C2065 错误
  • 每新增一个 QObject 子类,必须放在独立的 .h/.cpp 中,确保 AUTOMOC 正确生成 moc_*.cpp
  • 新文件需同步添加到 CMakeLists.txt 的 add_executable 列表

小结

这个项目的设计收获:

  1. WsBridge 桥接层让 UI 与 Core 真正解耦,UI 重写不动一行 Core 代码
  2. 职责单一:Controller 管生命周期、ConnectionMgr 管连接表、Router 管路由,三者互不侵入
  3. 无状态 Router 用 signal 触发发送,可以独立测试广播/单播逻辑
http://www.jsqmd.com/news/657638/

相关文章:

  • 130万对像素级对齐:SOMA-1M如何打通遥感多模态数据的“最后一公里“
  • 图片批量微调原创工具:18种图像处理+4种EXIF修改,完整功能解析
  • AI硬件洗牌,录音笔逆势升温!谁能在这场竞争中脱颖而出?
  • 英雄联盟智能工具箱:重新定义你的游戏体验
  • 2026沈阳GEO本地营销推广平台强势来袭:新私域助力企业破局AI搜索困局 - 品牌策略主理人
  • 贾子逆算子(KIO):面向大语言模型的主动式幻觉抑制与逻辑校准元算子
  • 别再乱用‘jet’了!用Matplotlib做数据可视化,这5个Colormaps选择技巧让你图表更专业
  • APK加固效果验证指南:如何判断防破解方案靠不靠谱?
  • 告别C语言硬编码!用lvglpp在ESP32上快速构建嵌入式GUI(附完整项目配置)
  • OpenClaw如何安装?2026年4月阿里云1分钟超简单云端搭建及百炼Coding Plan教程
  • Arduino IDE串口调试工具终极指南:5分钟掌握实时数据交互技巧
  • 无感定位筑基空间计算,镜像视界打造数字孪生视频孪生全场景方案
  • 科学图像分析难题破解:3个步骤让Fiji成为你的得力助手
  • 别再傻傻点图标了!用CMD启动mstsc远程桌面,这5个参数让你效率翻倍
  • apache httpd 后缀解析
  • GRBL移植实战(一):从AVR到ARM的引脚映射与平台适配
  • 保姆级教程:用YOLOv8-seg和DeepSORT在Windows上实现车辆计数与轨迹追踪
  • 告别Tesseract-OCR配置陷阱:从“tesseract is not installed”到“Error opening data file”的实战排错指南
  • 明日方舟游戏自动化助手终极指南:10分钟实现一键日常
  • 如何快速掌握缠论可视化分析:通达信插件终极指南
  • 如何通过游戏化编程轻松掌握Python与JavaScript:CodeCombat终极指南
  • 免费音频转换器终极指南:如何在5分钟内完成跨平台音频格式转换
  • 3分钟掌握Windows窗口置顶技巧:AlwaysOnTop提升多任务效率200%
  • 2026年口碑好的临安农家乐推荐榜单:临安民宿、临安农家乐吃住、临安农家乐、临安农家乐吃住、临安浙西大峡谷农家乐、临安浙西大龙湾农家乐、临安龙井峡漂流农家乐选择指南 - 海棠依旧大
  • 告别gRPC的臃肿?200行C++代码带你实现一个极简版Protorpc服务端
  • 终极飞书文档转Markdown解决方案:本地安全转换的完整指南
  • apache 文件上传 (CVE-2017-15715)
  • IgH EtherCAT 从入门到精通:第 9 章 过程数据域(Domain)管理
  • 别再只用散点图了!用make_circles和make_moons生成的数据,教你玩转5种可视化技巧(附完整代码)
  • AI赋能研发革命:从辅助工具到核心引擎,揭秘研发智能大模型如何重塑未来!