qt QWebSocket详解

1、概述

QWebSocket是Qt网络模块中的一个类,用于实现WebSocket协议的通信。WebSocket是一种全双工的通信协议,允许在客户端和服务器之间建立实时的双向通信。QWebSocket提供了对WebSocket协议的支持,使得开发者能够在Qt应用中方便地实现实时通信功能。它在需要实时数据传输、消息推送等场景中非常常见,如聊天室、实时数据流、在线游戏等

2、重要方法

  • QWebSocket(const QString &origin = QString(), QWebSocketProtocol::Version version = QWebSocketProtocol::VersionLatest, QObject *parent = nullptr):构造函数,用于创建一个QWebSocket对象。origin参数指定了WebSocket连接的来源,version参数指定了WebSocket协议的版本,parent参数指定了父对象。

  • virtual ~QWebSocket() override:析构函数,用于销毁QWebSocket对象。

  • void abort():立即关闭WebSocket连接,不发送关闭帧。

  • qint64 bytesToWrite() const:返回待发送的字节数。

  • QWebSocketProtocol::CloseCode closeCode() const:返回WebSocket连接关闭的原因代码。

  • QString closeReason() const:返回WebSocket连接关闭的原因文本。

  • QAbstractSocket::SocketError error() const:返回最近一次发生的错误类型。

  • QString errorString() const:返回最近一次错误的描述信息。

  • bool flush():尝试将所有待发送的数据发送出去。

  • void ignoreSslErrors(const QList<QSslError> &errors):忽略指定的SSL错误。

  • bool isValid() const:检查WebSocket连接是否有效。

  • QHostAddress localAddress() const:返回本机的IP地址。

  • quint16 localPort() const:返回本机的端口号。

  • const QMaskGenerator *maskGenerator() const:返回当前使用的掩码生成器。

  • QString origin() const:返回WebSocket连接的来源。

  • QAbstractSocket::PauseModes pauseMode() const:返回当前的暂停模式。

  • QHostAddress peerAddress() const:返回对端的IP地址。

  • QString peerName() const:返回对端的主机名。

  • quint16 peerPort() const:返回对端的端口号。

  • QNetworkProxy proxy() const:返回当前使用的代理。

  • qint64 readBufferSize() const:返回读取缓冲区的大小。

  • QNetworkRequest request() const:返回当前的网络请求。

  • QUrl requestUrl() const:返回请求的URL。

  • QString resourceName() const:返回资源名称。

  • void resume():恢复暂停的连接。

  • qint64 sendBinaryMessage(const QByteArray &data):发送一个二进制消息。

  • qint64 sendTextMessage(const QString &message):发送一个文本消息。

  • void setMaskGenerator(const QMaskGenerator *maskGenerator):设置掩码生成器。

  • void setPauseMode(QAbstractSocket::PauseModes pauseMode):设置暂停模式。

  • void setProxy(const QNetworkProxy &networkProxy):设置代理。

  • void setReadBufferSize(qint64 size):设置读取缓冲区的大小。

  • void setSslConfiguration(const QSslConfiguration &sslConfiguration):设置SSL配置。

  • QSslConfiguration sslConfiguration() const:返回当前的SSL配置。

  • QAbstractSocket::SocketState state() const:返回当前的连接状态。

  • QWebSocketProtocol::Version version() const:返回当前使用的WebSocket协议版本。

  • void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CloseCodeNormal, const QString &reason = QString()):关闭WebSocket连接,可以指定关闭代码和原因。

  • void ignoreSslErrors():忽略所有SSL错误。

  • void open(const QNetworkRequest &request):使用QNetworkRequest打开WebSocket连接。

  • void open(const QUrl &url):使用URL打开WebSocket连接。

  • void ping(const QByteArray &payload = QByteArray()):发送一个Ping帧,可选地携带负载。

3、信号

  • void aboutToClose():即将关闭连接时发出。

  • void binaryFrameReceived(const QByteArray &frame, bool isLastFrame):收到二进制帧时发出。

  • void binaryMessageReceived(const QByteArray &message):收到二进制消息时发出。

  • void bytesWritten(qint64 bytes):成功写入字节时发出。

  • void connected():连接成功时发出。

  • void disconnected():连接断开时发出。

  • void error(QAbstractSocket::SocketError error):发生错误时发出。

  • void pong(quint64 elapsedTime, const QByteArray &payload):收到Pong响应时发出。

  • void preSharedKeyAuthenticationRequired(QSslPreSharedKeyAuthenticator *authenticator):需要预共享密钥认证时发出。

  • void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator):需要代理认证时发出。

  • void readChannelFinished():读取通道关闭时发出。

  • void sslErrors(const QList<QSslError> &errors):SSL错误发生时发出。

  • void stateChanged(QAbstractSocket::SocketState state):连接状态改变时发出。

  • void textFrameReceived(const QString &frame, bool isLastFrame):收到文本帧时发出。

  • void textMessageReceived(const QString &message):收到文本消息时发出。

4、实例

复制代码
//.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QDir>
#include <iomanip>
#include <sstream>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE


#include <QDebug>
#include <QWebSocketServer>
#include <QtWebSockets>


class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    //server
    QWebSocketServer* m_server = nullptr;
    QList<QWebSocket*> m_clients;

    //client
    QWebSocket m_client;
public slots:
    void on_disconnected();
    void on_textMessageReceived(const QString &message);

    void connected();
    void disconnected();
    void textMessageReceived(const QString &message);
private slots:

    void on_pushButton_5_clicked();

    void on_pushButton_6_clicked();

    void on_pushButton_2_clicked();

    void on_pushButton_clicked();


    void on_newConnection();            // 有新的客户端连接
    void on_closed();                   // 关闭监听成功
private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

//.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"

#include <QLabel>
#include <QVBoxLayout>
#include <QPushButton>
#include <QPushButton>


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);


    setWindowTitle("WebSocket");

    m_server = new QWebSocketServer("web服务端", QWebSocketServer::NonSecureMode, this);
    connect(m_server, &QWebSocketServer::newConnection, this, &MainWindow::on_newConnection);
    connect(m_server, &QWebSocketServer::closed, this, &MainWindow::on_closed);

    connect(&m_client, &QWebSocket::connected, this, &MainWindow::connected);
    connect(&m_client, &QWebSocket::textFrameReceived, this, &MainWindow::textMessageReceived);
    connect(&m_client, &QWebSocket::disconnected, this, &MainWindow::disconnected);

}

MainWindow::~MainWindow()
{
    delete ui;
}

/**
 * @brief 有新的客户端发起连接
 */
void MainWindow::on_newConnection()
{
    QWebSocket* client = m_server->nextPendingConnection();   // 获取连接成功的客户端

    connect(client, &QWebSocket::textMessageReceived, this, &MainWindow::on_textMessageReceived);
    connect(client, &QWebSocket::disconnected, this, &MainWindow::on_disconnected);

    // 将所有客户端加入列表
    m_clients << client;
    ui->textEdit_3->append(QString("[%1:%2] 连接成功!").arg(client->peerAddress().toString()).arg(client->peerPort()));
}

/**
 * @brief 服务端关闭监听,关闭后不再接收新的客户端的连接请求
 */
void MainWindow::on_closed()
{
    ui->textEdit->append("服务端关闭监听!");
    ui->pushButton_5->setText("开启监听");
}


void MainWindow::on_pushButton_5_clicked()
{
    //TcpServer::get()->startServer(ui->lineEdit_5->text().toInt());
    if(!m_server->isListening())
    {
        bool ret = m_server->listen(QHostAddress::AnyIPv4, ui->lineEdit_5->text().toInt());
        if(ret)
        {
            ui->textEdit_3->append(QString("开始监听:%1").arg(m_server->serverUrl().toString()));
            ui->pushButton_5->setText("停止");
        }
    }
    else
    {
        m_server->close();
    }
}

/**
 * @brief 向所有连接的客户端发送数据
 */
void MainWindow::on_pushButton_6_clicked()
{
    QString data = ui->textEdit_4->toPlainText();
    for(auto client : m_clients)
    {
        client->sendTextMessage(data);
    }
}

/**
 * @brief 断开连接时移除对应的客户端
 */
void MainWindow::on_disconnected()
{
    QWebSocket *socket = qobject_cast<QWebSocket *>(sender());
    for(int i = 0; i < m_clients.count(); ++i)
    {
        if(m_clients.at(i) == socket)
        {
            disconnect(socket, &QWebSocket::textMessageReceived, this, &MainWindow::on_textMessageReceived);
            disconnect(socket, &QWebSocket::disconnected, this, &MainWindow::on_disconnected);
            m_clients.removeAt(i);
            break;
        }
    }
    ui->textEdit->append(QString("[%1:%2] 断开连接!").arg(socket->peerAddress().toString()).arg(socket->peerPort()));
}

/**
 * @brief          接收信息并将信息转发给所有客户端
 * @param message
 */
void MainWindow::on_textMessageReceived(const QString &message)
{
    QWebSocket *socket = qobject_cast<QWebSocket *>(sender());
    for(auto client : m_clients)
    {
        if(client != socket)   // 向所有连接的客户端转发信息,除了当前信息的发出者
        {
            client->sendTextMessage(message);
        }
    }
    ui->textEdit_3->append(QString("[%1:%2] %3").arg(socket->peerAddress().toString()).arg(socket->peerPort()).arg(message));
}


void MainWindow::connected()
{
    ui->textEdit_2->append("连接成功!");
}

void MainWindow::disconnected()
{
    ui->textEdit_2->append("断开连接!");
}

/**
 * @brief          接收数据
 * @param message
 */
void MainWindow::textMessageReceived(const QString &message)
{
    ui->textEdit_2->append(message);
}

void MainWindow::on_pushButton_2_clicked()
{
    m_client.open(QUrl(ui->lineEdit->text().trimmed()));
}


void MainWindow::on_pushButton_clicked()
{
    QString data = ui->textEdit->toPlainText();
    if(m_client.state() == QAbstractSocket::ConnectedState)    // 判断是否连接
    {
        m_client.sendTextMessage(data);
    }
}

源码下载:点击跳转​​​​​​​

觉得有帮助的话,打赏一下呗。。

相关推荐
小短腿的代码世界1 天前
Qt Bluetooth源码深度解析:从HCI协议到跨平台API的完整架构
开发语言·qt·架构
小短腿的代码世界1 天前
Qt WebEngine多进程架构与IPC通信:从Chromium多进程到Qt信号槽融合
qt·架构·系统架构
尘中远1 天前
【Qwt 7.0 系列】快速入门与核心新特性概览 —— 更现代的 Qt 数据可视化库
qt·数据可视化·绘图·qwt·科学绘图
初阳7851 天前
【Qt】系统相关(3)——多线程
qt
初阳7851 天前
【Qt】系统相关(2)——文件
开发语言·qt
尘中远2 天前
【Qwt 7.0 系列】坐标轴与刻度系统 —— 刻度引擎、网格、图例与刻度朝内
qt·数据可视化·qcustomplot·qwt·工业软件·科学绘图
sycmancia2 天前
Qt——多线程间的互斥
开发语言·qt
尘中远2 天前
【Qwt 7.0 系列】常用图表类型实战 —— 柱状图、散点图、箱线图与直方图
qt·qwt·工业软件·科学绘图
尘中远2 天前
【Qwt 7.0 系列】交互功能详解 —— 平移、缩放、坐标轴交互与数据拾取
qt·数据可视化·绘图·qcustomplot·qwt·科学绘图
sycmancia2 天前
Qt——进程与线程的概念
qt