日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Qt WebSocket服务端的简单Demo

發布時間:2025/3/15 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Qt WebSocket服务端的简单Demo 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

WebSocket服務端:QWebSocketServer

目錄

  • WebSocket服務端:QWebSocketServer
  • **背景**:
  • **QWebSocketServer 簡單使用介紹:**
  • 具體開發過程:
  • 主要關鍵代碼分析:
    • 1、服務開啟
    • 2、服務停止:
    • 3、向指定客戶端發送數據
    • 4、響應新接入的客戶端
    • 5、關閉所有的客戶端
    • 6、斷開其中與某個客戶端的連接
    • 7、接收客戶端的數據
    • 8、異常的處理
    • 9、最后在類頭文件添加相關信號,供其他對象關聯調用。
    • 10、窗體的實現:
  • 總結:

背景

最近遇到一個項目要開發一個服務,該服務通過websocket 傳出數據。于是先從簡單的實現開始吧。

QWebSocketServer 簡單使用介紹:

1、Qt對websocket的封裝分為服務端和客戶端,分別使用QWebSocketServer和QWebSocket。

2、QWebSocketServer 和 QTcpServer 都是基于QAbstractSocket模型的。所以可以類似QTcpServer的開發,它們行為相同。使用參照QTcpServer。

3、偵聽:調用listen()讓服務器監聽傳入的連接。

4、接入新的客戶端連接:每次客戶端連接到服務器時都會發出newConnection()信號。調用nextPendingConnection()將等待接入的連接接受為已連接的QWebSocket。函數返回指向QabstractSocket::ConnectedState中QWebSocket的指針,可以使用該指針與客戶端通信。

5、異常處理: 如果發生錯誤,ServerError()返回錯誤類型,并且可以調用ErrorString()以獲取對所發生情況的人類可讀描述。

6、停止接收新的接入:調用close()將使QWebSocketServer停止偵聽傳入的連接。

7、注意:

  • QWebSocket服務器當前不支持WebSocket擴展和WebSocket子工具。

  • 使用自簽名證書時,Firefox bug
    594502會阻止firefox連接到安全的Websocket服務器。要解決此問題,請首先使用https瀏覽到安全WebSocket服務器。Firefox將指示證書無效。從這里開始,可以將證書添加到異常中。在這之后,安全WebSockets連接應該可以工作。

  • QWebSocketServer僅支持WebSocket協議的版本13,如RFC6455所述。

8、服務器安全設置:
枚舉
enum QWebSocketServer::SslMode
指示服務器是通過wss(SecureMode)還是ws(NonSecureMode)運行。

具體開發過程:

1、在工程文件夾中添加: `QT += websockets` 2、包含類 `#include <QWebSocketServer>` 3、創建對象:使用時先new一個QWebSocketServer,傳入服務器名稱和是否使用安全模式(安全模式wss,非安全模式ws),然后關聯其newConnected(),closed(),serverError()。 4、當收到新的連接后,則是轉換為QWebSocket,然后關聯其connected(),disconnected(),error(),textFrameReceived()(或者textMessageReceived()信號,兩個收到消息的信號都會觸發),發送調用sendTextMessage()函數即。 5、為了更好的管理代碼,建一個類來管理webSocketServer class WebSocketServerManager : public QObject{Q_OBJECT public:explicit WebSocketServerManager(QString serverName,QWebSocketServer::SslMode secureMode = QWebSocketServer::NonSecureMode,QObject *parent = 0);~WebSocketServerManager();public:bool running() const;} 6、在該類中添加槽函數成員以及私有變量:如服務開啟,服務停止,服務關閉等 public slots:void slot_start(QHostAddress hostAddress = QHostAddress(QHostAddress::Any), qint32 port = 10080);void slot_stop();void slot_sendData(QString ip, qint32 port, QString message);protected slots:void slot_newConnection();void slot_serverError(QWebSocketProtocol::CloseCode closeCode);void slot_closed();protected slots:void slot_disconnected();void slot_error(QAbstractSocket::SocketError error);void slot_textFrameReceived(const QString &frame, bool isLastFrame);void slot_textMessageReceived(const QString &message);private:QString _serverName;QWebSocketServer::SslMode _sslMode;bool _running;QWebSocketServer *_pWebSocketServer;QHash<QString, QWebSocket*> _hashIpPort2PWebSocket;QHostAddress _listenHostAddress;qint32 _listenPort;

主要關鍵代碼分析:

1、服務開啟

void WebSocketServerManager::slot_start(QHostAddress hostAddress, qint32 port) {if(_running) //如果服務已經開啟{qDebug() << __FILE__ << __LINE__<< "Failed to" << __FUNCTION__ << "it's already running...";return;}if(!_pWebSocketServer) //如果沒有服務,則創建服務{_pWebSocketServer = new QWebSocketServer(_serverName, _sslMode, 0);connect(_pWebSocketServer, SIGNAL(newConnection()), this, SLOT(slot_newConnection()));connect(_pWebSocketServer, SIGNAL(closed()), this, SLOT(slot_closed()));connect(_pWebSocketServer, SIGNAL(serverError(QWebSocketProtocol::CloseCode)),this , SLOT(slot_serverError(QWebSocketProtocol::CloseCode)));}_listenHostAddress = hostAddress;_listenPort = port;//開啟偵聽_pWebSocketServer->listen(_listenHostAddress, _listenPort);//更新標志狀態_running = true; }

2、服務停止:

void WebSocketServerManager::slot_stop() {if(!_running){qDebug() << __FILE__ << __LINE__<< "Failed to" << __FUNCTION__<< ", it's not running...";return;}else{qDebug() << __FILE__ << __LINE__<< "connect to" << __FUNCTION__<< ", it's running...";}_running = false;_pWebSocketServer->close(); }

注意:Qt 有一項很重要的調試工具qDebug(), 而且可以指定文件到行和函數體。

3、向指定客戶端發送數據

void WebSocketServerManager::slot_sendData(QString ip, qint32 port, QString message) {QString key = QString("%1-%2").arg(ip).arg(port);if(_hashIpPort2PWebSocket.contains(key)){_hashIpPort2PWebSocket.value(key)->sendTextMessage(message);} }

注意到這里使用了容器,這使得我們更方便管理客戶端。

4、響應新接入的客戶端

void WebSocketServerManager::slot_newConnection() {QWebSocket *pWebSocket = _pWebSocketServer->nextPendingConnection();connect(pWebSocket, SIGNAL(disconnected()), this, SLOT(slot_disconnected()));connect(pWebSocket, SIGNAL(error(QAbstractSocket::SocketError)),this , SLOT(slot_error(QAbstractSocket::SocketError)));// 既會觸發frame接收也會觸發message接收 // connect(pWebSocket, SIGNAL(textFrameReceived(QString,bool)), // this , SLOT(slot_textFrameReceived(QString,bool)));connect(pWebSocket, SIGNAL(textMessageReceived(QString)),this , SLOT(slot_textMessageReceived(QString)));_hashIpPort2PWebSocket.insert(QString("%1-%2").arg(pWebSocket->peerAddress().toString()).arg(pWebSocket->peerPort()),pWebSocket);qDebug() << __FILE__ << __LINE__ << pWebSocket->peerAddress().toString() << pWebSocket->peerPort();emit signal_conncted(pWebSocket->peerAddress().toString(), pWebSocket->peerPort()); }

5、關閉所有的客戶端

遍歷當前客戶端,逐一關閉。

void WebSocketServerManager::slot_closed() {QList<QWebSocket *> _listWebSocket = _hashIpPort2PWebSocket.values();for(int index = 0; index < _listWebSocket.size(); index++){_listWebSocket.at(index)->close();}_hashIpPort2PWebSocket.clear();emit signal_close(); }

6、斷開其中與某個客戶端的連接

void WebSocketServerManager::slot_disconnected() {qDebug() << __FILE__ << __LINE__ << __FUNCTION__;QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());if(!pWebSocket){return;}qDebug() << __FILE__ << __LINE__ << __FUNCTION__;emit signal_disconncted(pWebSocket->peerAddress().toString(), pWebSocket->peerPort());_hashIpPort2PWebSocket.remove(QString("%1-%2").arg(pWebSocket->peerAddress().toString()).arg(pWebSocket->peerPort())); }

7、接收客戶端的數據

void WebSocketServerManager::slot_textFrameReceived(const QString &frame, bool isLastFrame) {QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());if(!pWebSocket){return;}qDebug() << __FILE__ << __LINE__ << frame << isLastFrame;emit signal_textFrameReceived(pWebSocket->peerAddress().toString(), pWebSocket->peerPort(), frame, isLastFrame); }void WebSocketServerManager::slot_textMessageReceived(const QString &message) {QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());if(!pWebSocket){return;}emit signal_textMessageReceived(pWebSocket->peerAddress().toString(), pWebSocket->peerPort(), message); }

8、異常的處理

void WebSocketServerManager::slot_serverError(QWebSocketProtocol::CloseCode closeCode) {QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());if(!pWebSocket){return;}emit signal_error(pWebSocket->peerAddress().toString(), pWebSocket->peerPort(), _pWebSocketServer->errorString()); }void WebSocketServerManager::slot_error(QAbstractSocket::SocketError error) {QWebSocket *pWebSocket = dynamic_cast<QWebSocket *>(sender());if(!pWebSocket){return;}emit signal_error(pWebSocket->peerAddress().toString(), pWebSocket->peerPort(), pWebSocket->errorString()); }

9、最后在類頭文件添加相關信號,供其他對象關聯調用。

void signal_conncted(QString ip, qint32 port);void signal_disconncted(QString ip, qint32 port);void signal_sendTextMessageResult(QString ip, quint32 port, bool result);void signal_sendBinaryMessageResult(QString ip, quint32 port, bool result);void signal_error(QString ip, quint32 port, QString errorString);void signal_textFrameReceived(QString ip, quint32 port, QString frame, bool isLastFrame);void signal_textMessageReceived(QString ip, quint32 port,QString message);void signal_close();

10、窗體的實現:

布局一個窗體,將窗體中的控件與類對象WebSocketServerManager關聯。

webSocketServerWidget::webSocketServerWidget(QWidget *parent) :QWidget(parent),ui(new Ui::webSocketServerWidget) {ui->setupUi(this);setWindowTitle("WebSocket服務端Demo v1.0.0 ");ui->pushButton_listen->setEnabled(true);ui->pushButton_stop->setEnabled(false);ui->pushButton_send->setEnabled(false);_pWebSocketServerManager = new WebSocketServerManager("Test");connect(_pWebSocketServerManager, SIGNAL(signal_conncted(QString,qint32)),this , SLOT(slot_conncted(QString,qint32)));connect(_pWebSocketServerManager, SIGNAL(signal_disconncted(QString,qint32)),this , SLOT(slot_disconncted(QString,qint32)));connect(_pWebSocketServerManager, SIGNAL(signal_error(QString,quint32,QString)),this , SLOT(slot_error(QString,quint32,QString)));connect(_pWebSocketServerManager, SIGNAL(signal_textFrameReceived(QString,quint32,QString,bool)),this , SLOT(slot_textFrameReceived(QString,quint32,QString,bool)));connect(_pWebSocketServerManager, SIGNAL(signal_textMessageReceived(QString,quint32,QString)),this , SLOT(slot_textMessageReceived(QString,quint32,QString)));ui->lineEdit_ip->setText(getLocalIp()); }webSocketServerWidget::~webSocketServerWidget() {delete ui; }void webSocketServerWidget::slot_conncted(QString ip, qint32 port) {_strList << QString("%1-%2").arg(ip).arg(port);_hashIpPort2Message.insert(QString("%1-%2").arg(ip).arg(port), QString());_model.setStringList(_strList);ui->listView_ipPort->setModel(&_model);if(_strList.size() == 1){ui->listView_ipPort->setCurrentIndex(_model.index(0));} }void webSocketServerWidget::slot_disconncted(QString ip, qint32 port) {QString str = QString("%1-%2").arg(ip).arg(port);if(_strList.contains(str)){_strList.removeOne(str);_model.setStringList(_strList);ui->listView_ipPort->setModel(&_model);updateTextEdit();} }void webSocketServerWidget::slot_sendTextMessageResult(QString ip, quint32 port, bool result) { }void webSocketServerWidget::slot_sendBinaryMessageResult(QString ip, quint32 port, bool result) {}void webSocketServerWidget::slot_error(QString ip, quint32 port, QString errorString) {}void webSocketServerWidget::slot_textFrameReceived(QString ip, quint32 port, QString frame, bool isLastFrame) {if(_hashIpPort2Message.contains(QString("%1-%2").arg(ip).arg(port))){_hashIpPort2Message[QString("%1-%2").arg(ip).arg(port)]= _hashIpPort2Message[QString("%1-%2").arg(ip).arg(port)] +(_hashIpPort2Message[QString("%1-%2").arg(ip).arg(port)].size() == 0 ? "" :"\n") +QDateTime::currentDateTime().toString("yyyy-HH-mm hh:MM:ss:zzz") + "\n" + frame;}updateTextEdit(); }void webSocketServerWidget::slot_textMessageReceived(QString ip, quint32 port, QString message) {qDebug() << __FILE__ << __LINE__ << message;if(_hashIpPort2Message.contains(QString("%1-%2").arg(ip).arg(port))){_hashIpPort2Message[QString("%1-%2").arg(ip).arg(port)]= _hashIpPort2Message[QString("%1-%2").arg(ip).arg(port)] +(_hashIpPort2Message[QString("%1-%2").arg(ip).arg(port)].size() == 0 ? "" :"\n") +QDateTime::currentDateTime().toString("yyyy-HH-mm hh:MM:ss:zzz") + "\n" + message;}updateTextEdit(); }void webSocketServerWidget::slot_close() {_pWebSocketServerManager->slot_stop();_strList.clear();_model.setStringList(_strList);ui->listView_ipPort->setModel(&_model);ui->textEdit_recv->clear(); }void webSocketServerWidget::updateTextEdit() {int row = ui->listView_ipPort->currentIndex().row();if(row < 0){ui->textEdit_recv->setText("");return;}if(_hashIpPort2Message.contains(_strList.at(row))){ui->textEdit_recv->setText(_hashIpPort2Message.value(_strList.at(row)));} }QString webSocketServerWidget::getLocalIp() {QString localIp;QList<QHostAddress> list = QNetworkInterface::allAddresses();for(int index = 0; index < list.size(); index++){if(list.at(index).protocol() == QAbstractSocket::IPv4Protocol){//IPv4地址if (list.at(index).toString().contains("127.0.")){continue;}localIp = list.at(index).toString();break;}}return localIp; }void webSocketServerWidget::on_pushButton_listen_clicked() {_pWebSocketServerManager->slot_start(QHostAddress::Any, ui->spinBox->value());ui->pushButton_listen->setEnabled(false);ui->pushButton_stop->setEnabled(true);ui->pushButton_send->setEnabled(true); }void webSocketServerWidget::on_pushButton_stop_clicked() {_pWebSocketServerManager->slot_stop();ui->pushButton_listen->setEnabled(true);ui->pushButton_stop->setEnabled(false);ui->pushButton_send->setEnabled(false); }void webSocketServerWidget::on_listView_ipPort_clicked(const QModelIndex &index) {updateTextEdit(); }void webSocketServerWidget::on_pushButton_send_clicked() {int row = ui->listView_ipPort->currentIndex().row();if(_hashIpPort2Message.contains(_strList.at(row))){QString str = _strList.at(row);QStringList strlist = str.split("-");if(strlist.size() == 2){_pWebSocketServerManager->slot_sendData(strlist.at(0),strlist.at(1).toInt(),ui->textEdit_send->toPlainText());}} }

總結:

1、該示例代碼簡單實現了webSocketServer的創建。但是并沒有用到多線程的技術,所以對并發處理不不適合。

2、本示例對數據處理,和錯誤事件并沒有很好的解析,這需要后續實現。

總結

以上是生活随笔為你收集整理的Qt WebSocket服务端的简单Demo的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。