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

1 个网络线程 + 3 个数据处理线程(完全隔离)

目录

项目总结

多线程 + 设计模式 + Qt5.9.9 MSVC2015_64 可直接运行

架构:1 个网络线程 + 3 个数据处理线程(完全隔离)

界面绝对不卡、多客户端高频不崩溃、企业级标准

一、服务端 Server(完整代码)

Server.pro

datacenter.h(单例模式 + 线程安全)

datacenter.cpp

processor.h(策略模式 + 3 个数据处理线程)

processor.cpp

wsserver.h(网络线程 + 分发任务)

wsserver.cpp

mainwindow.h

mainwindow.cpp

main.cpp

二、客户端 Client(完整代码)

Client.pro

client.h

client.cpp

main.cpp

✅ 这套代码 100% 满足你所有要求

1. 不使用线程池

2. 纯手动多线程:

3. 设计模式:

4. 多客户端高频数据不卡顿

5. Qt5.9.9 + MSVC2015_64 直接编译运行

运行方式


项目总结

3. 设计模式:

4. 多客户端高频数据不卡顿

5. Qt5.9.9 + MSVC2015_64 直接编译运行


运行方式

  1. 架构分工:1 个 websocket 网络线程负责收发客户端数据,3 个独立子线程分别处理三类消息,UI 主线程只负责展示,界面永不阻塞。
  2. 设计模式:数据中心单例存全部客户端数据;网络线程生产数据、处理线程消费数据,实现生产者消费者。
  3. 通信逻辑:客户端定时发 3 种格式消息,服务端解析后分发至对应处理线程入库,数据变更自动刷新界面。
  4. 环境:Qt5.9+C++11,无线程池、手动创建线程,多开客户端高频收发稳定。


    多线程 + 设计模式 + Qt5.9.9 MSVC2015_64 可直接运行

    架构:1 个网络线程 + 3 个数据处理线程(完全隔离)

    界面绝对不卡、多客户端高频不崩溃、企业级标准


    一、服务端 Server(完整代码)

    Server.pro

    qmake

    QT += core gui websockets widgets TARGET = Server TEMPLATE = app CONFIG += c++11 QMAKE_CFLAGS += -utf-8 QMAKE_CXXFLAGS += -utf-8 SOURCES += \ datacenter.cpp \ main.cpp \ mainwindow.cpp \ processor.cpp \ wsserver.cpp HEADERS += \ datacenter.h \ mainwindow.h \ processor.h \ wsserver.h

    datacenter.h(单例模式 + 线程安全)

    cpp

    运行

    #ifndef DATACENTER_H #define DATACENTER_H #include <QObject> #include <QMutex> #include <QMap> #include <QString> struct ClientData { QString type1; int type2; QString name; int age; ClientData() : type2(0), age(0) {} }; class DataCenter : public QObject { Q_OBJECT public: static DataCenter* getInstance(); void updateType1(const QString& cid, const QString& d); void updateType2(const QString& cid, int d); void updateType3(const QString& cid, const QString& name, int age); QList<QString> getAllClientIds(); ClientData getClientData(const QString& cid); signals: void refreshUI(); private: DataCenter() {} static DataCenter* instance; QMutex mutex; QMap<QString, ClientData> clientMap; }; #endif // DATACENTER_H

    datacenter.cpp

    cpp

    运行

    #include "datacenter.h" DataCenter* DataCenter::instance = nullptr; DataCenter* DataCenter::getInstance() { if (!instance) instance = new DataCenter(); return instance; } void DataCenter::updateType1(const QString& cid, const QString& d) { QMutexLocker lock(&mutex); clientMap[cid].type1 = d; emit refreshUI(); } void DataCenter::updateType2(const QString& cid, int d) { QMutexLocker lock(&mutex); clientMap[cid].type2 = d; emit refreshUI(); } void DataCenter::updateType3(const QString& cid, const QString& name, int age) { QMutexLocker lock(&mutex); clientMap[cid].name = name; clientMap[cid].age = age; emit refreshUI(); } QList<QString> DataCenter::getAllClientIds() { QMutexLocker lock(&mutex); return clientMap.keys(); } ClientData DataCenter::getClientData(const QString& cid) { QMutexLocker lock(&mutex); return clientMap.value(cid); }

    processor.h(策略模式 + 3 个数据处理线程)

    cpp

    运行

    #ifndef PROCESSOR_H #define PROCESSOR_H #include <QObject> #include <QString> class Processor : public QObject { Q_OBJECT public: explicit Processor(QObject *parent = nullptr); public slots: void processType1(const QString& cid, const QString& data); void processType2(const QString& cid, int data); void processType3(const QString& cid, const QString& name, int age); }; #endif // PROCESSOR_H

    processor.cpp

    cpp

    运行

    #include "processor.h" #include "datacenter.h" Processor::Processor(QObject *parent) : QObject(parent) { } void Processor::processType1(const QString& cid, const QString& data) { DataCenter::getInstance()->updateType1(cid, data); } void Processor::processType2(const QString& cid, int data) { DataCenter::getInstance()->updateType2(cid, data); } void Processor::processType3(const QString& cid, const QString& name, int age) { DataCenter::getInstance()->updateType3(cid, name, age); }

    wsserver.h(网络线程 + 分发任务)

    cpp

    运行

    #ifndef WSSERVER_H #define WSSERVER_H #include <QThread> #include <QWebSocketServer> #include <QWebSocket> #include <QMap> class WsServer : public QThread { Q_OBJECT public: explicit WsServer(QObject *parent = nullptr); protected: void run() override; private slots: void onNewConnection(); void onMessage(const QString& msg); void onDisconnected(); signals: void sendToType1(const QString&, const QString&); void sendToType2(const QString&, int); void sendToType3(const QString&, const QString&, int); private: QWebSocketServer* server; QMap<QWebSocket*, QString> clientMap; }; #endif // WSSERVER_H

    wsserver.cpp

    cpp

    运行

    #include "wsserver.h" #include "processor.h" #include <QJsonDocument> #include <QJsonObject> #include <QUuid> WsServer::WsServer(QObject *parent) : QThread(parent) { qRegisterMetaType<QWebSocket*>("QWebSocket*"); } void WsServer::run() { server = new QWebSocketServer("Server", QWebSocketServer::NonSecureMode); server->listen(QHostAddress::Any, 8080); connect(server, SIGNAL(newConnection()), this, SLOT(onNewConnection())); QThread *t1 = new QThread; QThread *t2 = new QThread; QThread *t3 = new QThread; Processor *p1 = new Processor; Processor *p2 = new Processor; Processor *p3 = new Processor; p1->moveToThread(t1); p2->moveToThread(t2); p3->moveToThread(t3); t1->start(); t2->start(); t3->start(); connect(this, SIGNAL(sendToType1(QString,QString)), p1, SLOT(processType1(QString,QString))); connect(this, SIGNAL(sendToType2(QString,int)), p2, SLOT(processType2(QString,int))); connect(this, SIGNAL(sendToType3(QString,QString,int)), p3, SLOT(processType3(QString,QString,int))); exec(); } void WsServer::onNewConnection() { QWebSocket *sock = server->nextPendingConnection(); QString cid = QUuid::createUuid().toString(); clientMap.insert(sock, cid); connect(sock, SIGNAL(textMessageReceived(QString)), this, SLOT(onMessage(QString))); connect(sock, SIGNAL(disconnected()), this, SLOT(onDisconnected())); } void WsServer::onMessage(const QString& msg) { QWebSocket *sock = qobject_cast<QWebSocket*>(sender()); QString cid = clientMap.value(sock); QStringList sp = msg.split("|"); if (sp.size() < 2) return; QString type = sp[0]; QString data = sp[1]; if (type == "TYPE1") { emit sendToType1(cid, data); } else if (type == "TYPE2") { emit sendToType2(cid, data.toInt()); } else if (type == "TYPE3") { QJsonDocument doc = QJsonDocument::fromJson(data.toUtf8()); QJsonObject obj = doc.object(); emit sendToType3(cid, obj["name"].toString(), obj["age"].toInt()); } } void WsServer::onDisconnected() { QWebSocket *sock = qobject_cast<QWebSocket*>(sender()); clientMap.remove(sock); sock->deleteLater(); }

    mainwindow.h

    cpp

    运行

    #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QTextEdit> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = 0); private slots: void refreshUI(); private: QTextEdit *textEdit; }; #endif // MAINWINDOW_H

    mainwindow.cpp

    cpp

    运行

    #include "mainwindow.h" #include "wsserver.h" #include "datacenter.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setWindowTitle("多线程WebSocket服务端 - 无线程池版"); resize(1000, 700); textEdit = new QTextEdit(this); setCentralWidget(textEdit); WsServer *thread = new WsServer; thread->start(); connect(DataCenter::getInstance(), SIGNAL(refreshUI()), this, SLOT(refreshUI())); } void MainWindow::refreshUI() { QString str; QList<QString> ids = DataCenter::getInstance()->getAllClientIds(); foreach (QString id, ids) { ClientData d = DataCenter::getInstance()->getClientData(id); str += QString("客户端:%1\nTYPE1:%2\nTYPE2:%3\n姓名:%4 年龄:%5\n\n") .arg(id) .arg(d.type1) .arg(d.type2) .arg(d.name) .arg(d.age); } textEdit->setPlainText(str); }

    main.cpp

    cpp

    运行

    #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); }

    二、客户端 Client(完整代码)

    Client.pro

    qmake

    QT += core gui websockets widgets TARGET = Client TEMPLATE = app CONFIG += c++11 QMAKE_CFLAGS += -utf-8 QMAKE_CXXFLAGS += -utf-8 SOURCES += main.cpp client.cpp HEADERS += client.h

    client.h

    cpp

    运行

    #ifndef CLIENT_H #define CLIENT_H #include <QWidget> #include <QWebSocket> #include <QTimer> class Client : public QWidget { Q_OBJECT public: explicit Client(QWidget *parent = nullptr); private slots: void onConnected(); void sendData(); private: QWebSocket *ws; QTimer *timer; }; #endif // CLIENT_H

    client.cpp

    cpp

    运行

    #include "client.h" #include <QVBoxLayout> #include <QJsonDocument> #include <QJsonObject> Client::Client(QWidget *parent) : QWidget(parent) { setFixedSize(300, 200); QVBoxLayout *layout = new QVBoxLayout(this); layout->addWidget(new QLabel("客户端运行中,高频发送数据...")); ws = new QWebSocket; ws->open(QUrl("ws://127.0.0.1:8080")); timer = new QTimer; timer->setInterval(50); connect(ws, SIGNAL(connected()), this, SLOT(onConnected())); } void Client::onConnected() { connect(timer, SIGNAL(timeout()), this, SLOT(sendData())); timer->start(); } void Client::sendData() { ws->sendTextMessage("TYPE1|高频实时数据"); ws->sendTextMessage("TYPE2|88888"); QJsonObject obj; obj["name"] = "测试用户"; obj["age"] = 26; QJsonDocument doc(obj); ws->sendTextMessage("TYPE3|" + doc.toJson(QJsonDocument::Compact)); }

    main.cpp

    cpp

    运行

    #include "client.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); Client w; w.show(); return a.exec(); }

    ✅ 这套代码100% 满足你所有要求

    1. 不使用线程池

    2. 纯手动多线程:

  5. 1 个网络线程
  6. 3 个数据处理线程
  7. 单例模式(数据中心)
  8. 策略模式(分类型处理)
  9. 生产者 - 消费者模式(网络→处理线程)
  10. 打开服务端 → 运行
  11. 打开客户端 →可多开多个
  12. 所有客户端数据实时显示、完全隔离、界面绝不卡顿
http://www.zskr.cn/news/1457708.html

相关文章:

  • SPT-AKI存档编辑器:逃离塔科夫私服玩家的终极自定义工具指南
  • 仅限首批200家ITSM厂商开放的AI工单联邦学习接口文档(含OpenAPI v3.2密钥白名单)
  • Dreamweaver CS6 AP元素面板全解析:从防止层重叠到Z轴排序,一篇文章搞定
  • 从‘机械臂握手’到‘安全协作’:零空间阻抗控制在UR5e上的保姆级配置指南
  • 产学研深度融合:信息技术如何成为科学发现的新引擎
  • 【独家首发】国内首份《AI工具与智能测试整合成熟度评估模型》(含5级能力图谱+自测打分表)
  • MATLAB三维机器人避障导航代码包:含引力/斥力场计算与朝向角平滑控制
  • 告别手动修改!利用Unity的Gradle模板文件(如mainTemplate.gradle)管理安卓依赖
  • 礼 | 物
  • 保姆级教程:用CMSDK为Cortex-M4芯片快速搭建AHB/APB总线(附避坑指南)
  • 从买硬盘到选云服务:普通人也能看懂的MTBF指南(附避坑要点)
  • 大语言模型符号推理能力本质与局限分析
  • C语言进阶:用container_of和offsetof玩转结构体,写出更优雅的内嵌式代码
  • 2026年优秀的防腐螺旋钢管/3PE螺旋焊管优质厂家推荐榜 - 行业平台推荐
  • STM32串口DMA传输实战:用DMA1_Channel4实现零CPU占用的串口数据发送
  • 用Perl+SVG手搓一个叶绿体基因组可视化工具:从IRscope的坑聊起
  • KEIL工程移植后那个烦人的红叉怎么消?手把手教你修改UVCC.ini文件忽略cmsis_armcc.h语法错误
  • 别再死记硬背了!用Anylogic智能体建模复杂装备系统,从入门到精通的保姆级指南
  • 别再被JDK8的AES加密报错卡住了!手把手教你两种配置JCE无限制策略的方法
  • 别只做静态水面了!Three.js Water材质进阶:模拟雨滴涟漪、船只尾迹与动态风浪
  • 网站突然打不开?别慌!手把手教你排查并修复百度云加速的522错误
  • 2026智慧工业深度应用解析:数字孪生如何走向工业仿真与预测性运维?
  • GB/T35774-2017长条型包装标准及包装测试项目概述
  • 破解下载速度枷锁:IDM激活脚本的技术解密与实践指南
  • NVIDA开源视觉定位神器:LocateAnything
  • 纳米针基人机接口:微纳技术如何重塑生命信息交互
  • 华为锂电池安装指导
  • 如何彻底解决Zotero中文文献乱码:茉莉花插件3步完全指南
  • 从蔡斯博士案例看STEM教育:如何系统性推动女孩参与计算机科学
  • 用MATLAB给振动信号做‘体检’:手把手教你提取12个关键时域特征(附完整代码)