Qt服务端多线程的示例分析
发表于:2026-11-01 作者:千家信息网编辑
千家信息网最后更新 2026年11月01日,这篇文章给大家分享的是有关Qt服务端多线程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。该例子仅使用两个线程, 一个线程负责监听新的连接,一个线程用来处理已经建立
千家信息网最后更新 2026年11月01日Qt服务端多线程的示例分析
这篇文章给大家分享的是有关Qt服务端多线程的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。
该例子仅使用两个线程, 一个线程负责监听新的连接,一个线程用来处理已经建立连接的客户端事件(此处可以用一个线程池来提高性能)。消息接收加入了一一个简单分包机制,每条消息的前四个字节存储的是 uint32_t 类型,指该条消息整个长度, 这样就可以很好区分出每个消息。该代码在许多细节上有些不严谨的地方,仅供从参考
// tcpserver.hclass CClientSocket;class CTcpServer final : public QTcpServer{ Q_OBJECTpublic: explicit CTcpServer(QObject *parent = nullptr); virtual ~CTcpServer() override; void Listen(int _iPort); void Nortify(const QByteArray &_csMessage);protected: virtual void incomingConnection(qintptr socketDescriptor) override; virtual void timerEvent(QTimerEvent *event) override;public slots: void SLOT_ClientDisconnect();private: void _PackageMessage(QByteArray &_baMsg);private: QList> m_lstSocket; ///< 连接的客户端 QThread * m_pEventThd; ///< 事件线程}; // tcpserver.cppCTcpServer::CTcpServer(QObject *parent) : QTcpServer(parent), m_pEventThd(new QThread()){ m_lstSocket.clear();}CTcpServer::~CTcpServer(){}void CTcpServer::Listen(int _iPort){ this->listen(QHostAddress::Any, static_cast(_iPort)); m_pEventThd->start(); QObject::startTimer(5 * 1000);}void CTcpServer::Nortify(const QByteArray &_csMessage){ QByteArray baSendMsg = _csMessage; _PackageMessage(baSendMsg); for (auto pClientSocket : m_lstSocket) { pClientSocket->SendMsg(baSendMsg); } QThread::msleep(50);}void CTcpServer::incomingConnection(qintptr socketDescriptor){ qDebug() << "#################MainThread:" << QThread::currentThread() << m_pEventThd; std::shared_ptr pClient = std::make_shared(socketDescriptor, nullptr); connect(pClient.get(), &CClientSocket::SIGNAL_Disconneted, this, &CTcpServer::SLOT_ClientDisconnect); pClient->InitSocket(m_pEventThd); m_lstSocket.push_back(pClient); emit newConnection();}void CTcpServer::timerEvent(QTimerEvent *event){ this->Nortify("hello world");}void CTcpServer::SLOT_ClientDisconnect(){ CClientSocket *pClient = dynamic_cast(QObject::sender()); if (pClient) { for (const auto &index : m_lstSocket) { if (index.get() == pClient) { m_lstSocket.removeOne(index); return; } } }}void CTcpServer::_PackageMessage(QByteArray &_baMsg){ uint32_t iSize = static_cast(_baMsg.size()); iSize = ::ntohl(iSize); _baMsg.prepend(reinterpret_cast(&iSize), sizeof (iSize));} // clientsocketclass CClientSocket : public QTcpSocket{ Q_OBJECTprivate: struct TMsgCache { void Clear() { iSize = 0; baPacket = ""; } size_t iSize = 0; ///< 包的实际长度 去除包头长度 QByteArray baPacket = ""; ///< 原始字段 };public: explicit CClientSocket(int _iFd, QObject *parent = nullptr); virtual ~CClientSocket() override; void InitSocket(QThread * _pThread); void SendMsg(const QByteArray &_baMessage);protected: virtual void timerEvent(QTimerEvent *event) override;private: void _DeInitSocket(); void _UpdateHeartTime();private: Q_INVOKABLE void _StartCheckTimer(); Q_INVOKABLE void _SendMessage(const QByteArray &_baMessage);private slots: void SLOT_ReadyRead(); void SLOT_SocketError(QAbstractSocket::SocketError _eError); void SLOT_Disconnect();signals: void SIGNAL_Disconneted();private: QString m_sCabinetCode; ///< 柜体编号 qint64 m_iOldResponseTimeStamp; ///< 上一次响应的时间戳 int m_iTimeId; ///< 心跳包检测时间 TMsgCache m_tMsgCache; ///< 消息缓存结构体};// clientsoket.cpp#define READ_MAX_SIZE 1024CClientSocket::CClientSocket(int _iFd, QObject *parent) : QTcpSocket(parent){ this->setSocketDescriptor(_iFd); connect(this, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(SLOT_SocketError(QAbstractSocket::SocketError))); connect(this, &QTcpSocket::readyRead, this, &CClientSocket::SLOT_ReadyRead); connect(this, &QTcpSocket::disconnected, this, &CClientSocket::SLOT_Disconnect); m_iOldResponseTimeStamp = QDateTime::currentDateTime().toSecsSinceEpoch();}CClientSocket::~CClientSocket(){ this->close(); qDebug() << "###################CClientSocket destruct";}void CClientSocket::InitSocket(QThread *_pThread){ this->moveToThread(_pThread); QMetaObject::invokeMethod(this, &CClientSocket::_StartCheckTimer);}void CClientSocket::SendMsg(const QByteArray &_baMessage){ QMetaObject::invokeMethod(this, "_SendMessage", Q_ARG(const QByteArray&, _baMessage));}void CClientSocket::timerEvent(QTimerEvent *event){ if (m_iTimeId == event->timerId()) { if (abs(QDateTime::currentSecsSinceEpoch() - m_iOldResponseTimeStamp) > 60) { this->disconnectFromHost(); } }}void CClientSocket::_DeInitSocket(){ this->close(); QObject::killTimer(m_iTimeId); m_iTimeId = 0;}void CClientSocket::_UpdateHeartTime(){ m_iOldResponseTimeStamp = QDateTime::currentDateTime().toSecsSinceEpoch();}void CClientSocket::_StartCheckTimer(){ qDebug() << "##########################_StartCheckTimer"; m_iTimeId = QObject::startTimer(1000 * 5);}void CClientSocket::_SendMessage(const QByteArray &_baMessage){ if (this->isWritable()) { this->write(_baMessage); this->flush(); }}void CClientSocket::SLOT_ReadyRead(){ char cBuffer[READ_MAX_SIZE]; qint64 iReadSize = 0; QByteArray baNewCache; do{ iReadSize = this->read(cBuffer, READ_MAX_SIZE); if (iReadSize == -1) ///< 网络异常 { qDebug() << QString("############################Read Socket Error, %1:%2").arg(this->peerAddress().toString()) .arg(this->peerPort()); this->SLOT_Disconnect(); return; } if (iReadSize != 0) { baNewCache.append(cBuffer, static_cast(iReadSize)); } }while (iReadSize != 0); if (m_tMsgCache.baPacket.size() != 0) { baNewCache = m_tMsgCache.baPacket + baNewCache; } while (baNewCache.size() > 0) { if (baNewCache.size() > 4) { uint32_t iSize; if (m_tMsgCache.iSize == 0) { QByteArray baSize = baNewCache.mid(0, 4); ::memcpy(&iSize, baSize.data(), sizeof(iSize)); iSize = ::ntohl(iSize); } else{ iSize = m_tMsgCache.iSize; } if (baNewCache.size() >= static_cast(iSize)) // 分解出一个完整的消息包 { m_tMsgCache.baPacket = baNewCache.mid(4, static_cast(iSize - 4));// // 动作:推入到执行线程队列// m_pHandleMessageThd->Push(m_tMsgCache.baPacket ); // 重置缓存状态 m_tMsgCache.Clear(); // 检测下一个新的消息包 baNewCache = baNewCache.mid(static_cast(iSize)); } else { m_tMsgCache.iSize = iSize; m_tMsgCache.baPacket = baNewCache; break; } } else{ // 没有完整4字节长度值 m_tMsgCache.iSize = 0; m_tMsgCache.baPacket = baNewCache; break; } } this->_UpdateHeartTime();}void CClientSocket::SLOT_SocketError(QAbstractSocket::SocketError _eError){ qDebug() << QString("CClientSocket(%1:%2)disconnet, error:%3").arg(this->peerAddress().toString()) .arg(this->peerPort()).arg(_eError); _DeInitSocket(); emit SIGNAL_Disconneted();}void CClientSocket::SLOT_Disconnect(){ qDebug() << QString("client disconnect"); _DeInitSocket(); emit SIGNAL_Disconneted();} 感谢各位的阅读!关于"Qt服务端多线程的示例分析"这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!
线程
消息
长度
示例
分析
服务
事件
内容
字节
客户
客户端
时间
更多
篇文章
缓存
参考
检测
不错
严谨
原始
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
互联网与科技
互联网科技产业
科技平台互联网
盈实互联网科技
互联网科技网站
四川狮子座互联网科技
一五八零互联网科技
丰台科技园 互联网公司
四个字互联网科技公司取名
开启互联网科技时代小说
安控科技rtu产品工业互联网
玖二柒互联网科技公司待遇
互联网还是高科技吗
呼和浩特新华互联网科技学院
华夏恒生科技与互联网科技
华中科技大学互联网的牛人
35岁以上互联网科技行业
美国五大互联网科技公司市值多少
互联网科技博主张洲
互联网科技创新创业项目
什么是科技互联网
科技平台互联网
互联网属科技
济南华为互联网科技产业总部基地
温州喔噻互联网科技有限公司
深圳育鹏互联网科技有限公司招聘
徐州市互联网科技有限公司
互联网时代科技型公司的机会
互联网科技机房
互联网时代高科技布局