赞
踩
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
要是想了解QWebSocket的详细知识,还得移步到上一篇文章:
WebSocket 详解,以及用QWebSocket 实现服务端和客户端(含代码例子)-CSDN博客
本篇文章主要讲解如何利用QWebSocket 实现服务和客户之间的通讯
(1)首先创建了一个服务器的基类,主要实现了服务类的基本接口:
1、创建服务器:new QWebSocketServer
2、监听:listen
m_pWebSocketServer->listen(QHostAddress::LocalHost, mPort);//端口号
3、有新的连接,收到这个信号:QWebSocketServer::newConnection
4、获得新的客户端:nextPendingConnection
5、接收到信息时候,收到信号:QWebSocket::binaryMessageReceived
6、断开连接,收到信号:QWebSocket::disconnected注意:数据的接收和发送,有两种格式,二进制和文本的,具体按照实际需要的来选择;
(2)在服务器的基类上,封装一个具体使用的类,这个类,主要是添加了QThread,创建一个子线程来进行服务器的开启,监听和接收数据,不会影响主线程的事件。
接收和发送的数据,以二进制为例
(1)服务器基类:
服务器基类的头文件:
1)开启一个端口号为“9000”的服务器
2)监听的网路是:QHostAddress::Any
QHostAddress::Any表示服务端监听所有可用的网络接口。
它是一个特殊的IP地址,表示服务端可以接受来自任何IP地址的连接请求。
这通常用于在一个计算机上运行多个网络服务时,让服务端能够监听所有可用的网络接口,以便接受来自不同网络接口的连接请求。
注意:也可以监听具体的IP地址:
例如:QHostAddress(strLocalHostIp)
#ifndef WEBSOCKETSERVERBASE_H #define WEBSOCKETSERVERBASE_H #include <QObject> #include <QtWebSockets> QT_FORWARD_DECLARE_CLASS(QWebSocketServer) QT_FORWARD_DECLARE_CLASS(QWebSocket) QT_FORWARD_DECLARE_CLASS(QString) class WebsocketServerBase : public QObject { Q_OBJECT public: explicit WebsocketServerBase(QString serverName, quint16 port, QObject *parent = 0); virtual ~WebsocketServerBase(); signals: //客户端发来的数据 void sigProcessServerMessage(const QByteArray &data); public slots: //发送数据给客户端 void slotSendToAllClients(const QByteArray &data); //启动websocket服务器 void slotStartServer(); private slots: //处理新接入的连接 void slotNewConnection(); //处理链接断开的事件 void slotSocketDisconnected(); //接收数据,并转发 void slotProcessBinaryMessage(const QByteArray &message); public: //检测是否存在客户端 bool hadClients(); private: QWebSocketServer *m_pWebSocketServer = nullptr; QList<QWebSocket *> m_clients; unsigned short m_nPort = 9000; QString m_strServerName = "server"; }; #endif // WEBSOCKETSERVERBASE_H
服务器基类的源文件:
#include "websocketserverbase.h" #include<QDebug> static QString getIdentifier(QWebSocket *peer) { return QStringLiteral("%1:%2").arg(peer->peerAddress().toString(), peer->origin()); } WebsocketServerBase::WebsocketServerBase(QString serverName, quint16 port, QObject *parent) : QObject(parent) ,m_nPort(port) ,m_strServerName(serverName) { } WebsocketServerBase::~WebsocketServerBase() { if(m_pWebSocketServer) { m_pWebSocketServer->close(); //m_pWebSocketServer->abort(); m_pWebSocketServer->deleteLater(); } } //接收到外部发来的信息,转发给客户端 void WebsocketServerBase::slotSendToAllClients(const QByteArray &data) { qDebug() << __FUNCTION__; for (QWebSocket *pClient : qAsConst(m_clients)) { qDebug() << "data: " << data; pClient->sendBinaryMessage(data); } } bool WebsocketServerBase::hadClients() { return m_clients.size()>0; } void WebsocketServerBase::slotStartServer() { if(m_pWebSocketServer) return; m_pWebSocketServer = new QWebSocketServer(m_strServerName, QWebSocketServer::NonSecureMode, this); if (m_pWebSocketServer->listen(QHostAddress::Any, m_nPort)) { connect(m_pWebSocketServer, &QWebSocketServer::newConnection, this, &WebsocketServerBase::slotNewConnection); qDebug() << "WebSocket is start, port:" << m_nPort; } } void WebsocketServerBase::slotNewConnection() { auto pSocket = m_pWebSocketServer->nextPendingConnection(); QTextStream(stdout) << getIdentifier(pSocket) << " connected!\n"; qDebug() << "client connected!"; pSocket->setParent(this); //二进制数据的接收 connect(pSocket, &QWebSocket::binaryMessageReceived, this, &WebsocketServerBase::slotProcessBinaryMessage); connect(pSocket, &QWebSocket::disconnected, this, &WebsocketServerBase::slotSocketDisconnected); m_clients << pSocket; } void WebsocketServerBase::slotSocketDisconnected() { QWebSocket *pClient = qobject_cast<QWebSocket *>(sender()); QTextStream(stdout) << getIdentifier(pClient) << " disconnected!\n"; if (pClient) { m_clients.removeAll(pClient); pClient->deleteLater(); } } //接收客户端发来的数据,并转发出去 void WebsocketServerBase::slotProcessBinaryMessage(const QByteArray &data) { qDebug() << __FUNCTION__ << " data:" << data; emit sigProcessServerMessage(data); //test //slotSendToAllClients(data); }
(2)将服务器基类封装,改造下:(外面可以直接使用这个类进行通讯)
改造后服务器的头文件:
此处本例是使用回调函数将结果抛给上一层调用者,在qt里,完全可以用信号槽代替的。
#ifndef READERWEBSOCKETSERVER_H #define READERWEBSOCKETSERVER_H #include <QObject> #include "Singleton.h" // 回调函数,将websocket的结果抛给上层 typedef void(*recvMsgToSerial)(const QByteArray &byteArray); class WebsocketServerBase; class ReaderWebsocketServer : public QObject, public Singleton<ReaderWebsocketServer> { Q_OBJECT friend class Singleton<ReaderWebsocketServer>; public: explicit ReaderWebsocketServer(QObject *parent = 0); virtual ~ReaderWebsocketServer(); public: // 设置回调函数 void setCallBack(recvMsgToSerial pFunc, void* pUser = NULL); // 接收串口发来数据,转发给客户端 bool sendData(const QByteArray &byteArray); signals: //转发数据给客户端 void sigSendToAllClients(const QByteArray &data); private slots: //处理客户端发来的数据,转发给需要的地方 void slotProcessServerMessage(const QByteArray &data); private: WebsocketServerBase* m_pWsServer = nullptr; QThread* m_thdWsServer = nullptr; void* m_pUser; // 返回回调的对象 recvMsgToSerial m_pRecvMsgToSerial; // 回调 }; #endif // READERWEBSOCKETSERVER_H
改造后服务器的源文件:
#include "readerwebsocketserver.h" #include <QThread> #include <cstring> #include "websocketserverbase.h" ReaderWebsocketServer::ReaderWebsocketServer(QObject *parent) : QObject(parent) { m_thdWsServer = new QThread(); m_pWsServer = new WebsocketServerBase("reader", 9000); m_pWsServer->moveToThread(m_thdWsServer); connect(m_pWsServer, &WebsocketServerBase::sigProcessServerMessage, this, &ReaderWebsocketServer::slotProcessServerMessage); connect(this, &ReaderWebsocketServer::sigSendToAllClients, m_pWsServer, &WebsocketServerBase::slotSendToAllClients); connect(m_thdWsServer, &QThread::started, m_pWsServer, &WebsocketServerBase::slotStartServer); connect(m_thdWsServer, &QThread::finished, m_pWsServer, &WebsocketServerBase::deleteLater); connect(m_thdWsServer, &QThread::finished, m_thdWsServer, &WebsocketServerBase::deleteLater); m_thdWsServer->start(); } ReaderWebsocketServer::~ReaderWebsocketServer() { if(m_thdWsServer) { m_thdWsServer->quit(); m_thdWsServer->wait(); } if(m_pWsServer) { m_pWsServer->deleteLater(); } } void ReaderWebsocketServer::setCallBack(recvMsgToSerial pFunc, void *pUser) { if (nullptr != pFunc) m_pRecvMsgToSerial = pFunc; if (nullptr != pUser) m_pUser = pUser; } //接收串口发来数据,转发给客户端 bool ReaderWebsocketServer::sendData(const QByteArray &byteArray) { bool hadBnode = m_pWsServer->hadClients(); if (hadBnode) { emit sigSendToAllClients(byteArray); } } //处理客户端发来的数据,转发给需要的地方 void ReaderWebsocketServer::slotProcessServerMessage(const QByteArray &byteArray) { qDebug() << __FUNCTION__ ; m_pRecvMsgToSerial(byteArray); }
(1)首先创建了一个客户端的基类,主要实现了客户端的基本接口:
(2)在客户端基类上,封装一个具体使用的类:(外面可以直接使用这个类进行通讯)
这个类,主要是添加了QThread 和QTimer,QThread 创建一个子线程来进行服务器的开启,监听和接收数据,不会影响主线程的事件;QTimer主要是发心跳包,实现断开重连机制;
接收和发送的数据,以二进制为例
(1)客户端基类:
客户端基类的头文件:
/* * @Description: websocket客户端,用于与中间件通信 */ #pragma once #include <QObject> #include <QByteArray> class QTimer; class QWebSocket; class WebSocketBase : public QObject { Q_OBJECT public: WebSocketBase(QObject *parent = nullptr); ~WebSocketBase(); void setWebSocketUrl(QString strUrl=""); bool getConnectStatus(); int RecvFrom(QByteArray& byteArray); signals: void sigClientBinaryMessageReceived(const QByteArray &byteArray); //借用websocket的信号函数 public slots: void slotCreateDataRecWS();//创建websocket连接 void slotSendBinaryMessageMessage(const QByteArray &byteArray); void slotReconnect(); /*-<周期重连函数 */ void slotActiveReconnect(); private slots: void slotOnConnected(); /*-<socket建立成功后,触发该函数 */ void slotOnBinaryMessageReceived(const QByteArray &byteArray); /*-<收到Sev端的数据时,触发该函数 */ void slotOnDisConnected(); /*-<socket连接断开后,触发该函数 */ private: QWebSocket *m_pDataRecvWS; /*-<websocket类 */ QTimer *m_pTimer; /*-<周期重连Timer */ QString m_strURL; /*连接URL*/ bool m_bConnectStatus; /*-<websocket连接状态,连接成功:true;断开:false */ QByteArray m_byteArray; };
客户端基类的源文件:
#include "WebSocketBase.h" #include <QWebSocket> #include <QTimer> #include <QByteArray>   **网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。** **[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)** **一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!** Array; };
客户端基类的源文件:
#include "WebSocketBase.h" #include <QWebSocket> #include <QTimer> #include <QByteArray> [外链图片转存中...(img-shA8KnEV-1715675050058)] [外链图片转存中...(img-i6Y4lhfc-1715675050058)] **网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。** **[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)** **一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。