Qt_webSocket协议编程实战

Qt WebSocket 协议编程实战

1. WebSocket 协议概述

WebSocket 是一种基于单个 TCP 连接提供全双工(Full-Duplex)通信信道 的网络技术。与传统的 HTTP 请求/响应模型不同,WebSocket 在连接建立后,客户端与服务器可以双向、实时、低延迟地收发数据,无需反复握手。

  • 标准化 :IETF 将其标准化为 RFC 6455
  • 握手 :通过 HTTP 的 Upgrade 头完成协议升级(HTTP/1.1 101 Switching Protocols),握手完成后数据在同一个 TCP 连接上以**帧(frame)**的形式传输
  • 协议标识ws://(明文)与 wss://(基于 TLS 加密,默认端口 443)
  • 默认端口ws 为 80,wss 为 443
  • 典型用途:实时聊天、股票/行情推送、在线游戏、服务端主动推送通知等

在 Qt 中,QWebSocket 既可用于客户端 应用程序,也可用于服务器 端(配合 QWebSocketServer)构建 WebSocket 服务。


2. QWebSocket Class(客户端)

QWebSocket 继承自 QObject,用于在客户端发起并管理一个 WebSocket 连接。

2.1 头文件与链接

cpp 复制代码
#include <QWebSocket>
  • 需要在 .pro 文件中添加:QT += websockets
  • CMake 中:find_package(Qt6 COMPONENTS WebSockets REQUIRED) 并链接 Qt6::WebSockets

2.2 连接与断开

cpp 复制代码
QWebSocket socket;

// 发起连接(异步)
socket.open(QUrl("ws://localhost:1234"));

// 连接成功信号
connect(&socket, &QWebSocket::connected, this, [](){
    qDebug() << "Connected";
});

// 可选:设置是否忽略 SSL 错误(仅用于测试环境,生产谨慎)
connect(&socket, &QWebSocket::sslErrors, &socket,
        QOverload<const QList<QSslError>&>::of(&QWebSocket::ignoreSslErrors));

// 主动关闭
socket.close();

2.3 收发数据

cpp 复制代码
// 发送文本消息
socket.sendTextMessage(QStringLiteral("Hello, Server!"));

// 发送二进制消息
QByteArray data = QByteArray::fromHex("48656c6c6f");
socket.sendBinaryMessage(data);

// 接收文本消息
connect(&socket, &QWebSocket::textMessageReceived, this,
        [](const QString &msg){
    qDebug() << "Text received:" << msg;
});

// 接收二进制消息
connect(&socket, &QWebSocket::binaryMessageReceived, this,
        [](const QByteArray &data){
    qDebug() << "Binary received, size:" << data.size();
});

3. QWebSocketServer Class(服务器)

QWebSocketServer 用于在服务器端监听并接受 WebSocket 客户端连接,创建一个 WebSocket 服务。

3.1 启动服务器

cpp 复制代码
#include <QWebSocketServer>

QWebSocketServer server(QStringLiteral("My Server"),
                        QWebSocketServer::NonSecureMode); // 明文模式

// 或使用 SecureMode(需要配置 SSL 证书)
// QWebSocketServer server(QStringLiteral("My Server"),
//                         QWebSocketServer::SecureMode);

if (server.listen(QHostAddress::Any, 1234)) {
    qDebug() << "Listening on port" << server.serverPort();
}

3.2 处理新连接与消息

cpp 复制代码
// 新客户端接入
connect(&server, &QWebSocketServer::newConnection, this, [&server](){
    QWebSocket *client = server.nextPendingConnection();
    qDebug() << "New client:" << client->peerAddress().toString();

    connect(client, &QWebSocket::textMessageReceived, this,
            [client](const QString &msg){
        client->sendTextMessage("Echo: " + msg); // 回显
    });

    connect(client, &QWebSocket::disconnected, client, &QObject::deleteLater);
});

4. 相关 API 一览

4.1 QWebSocket 主要方法

方法 说明
open(const QUrl &url) 发起连接到指定 WebSocket 地址
close(CloseCode code = NormalClosure) 关闭连接
sendTextMessage(const QString &message) 发送文本消息
sendBinaryMessage(const QByteArray &data) 发送二进制消息
abort() 立即中止连接
requestUrl() 返回请求的 URL
state() 返回当前连接状态(QAbstractSocket::SocketState
error() / errorString() 获取错误信息

4.2 QWebSocket 主要信号

信号 说明
connected() 连接建立成功
disconnected() 连接断开
textMessageReceived(const QString &) 收到文本消息
binaryMessageReceived(const QByteArray &) 收到二进制消息
stateChanged(QAbstractSocket::SocketState) 连接状态变化
errorOccurred(QAbstractSocket::SocketError) 发生错误
sslErrors(const QList<QSslError> &) SSL 错误

4.3 QWebSocketServer 主要方法

方法 说明
listen(const QHostAddress &, quint16 port) 开始监听
nextPendingConnection() 取出下一个待处理的客户端连接
close() 停止监听
hasPendingConnections() 是否有待处理的连接
serverPort() 返回实际监听的端口

4.4 QWebSocketServer 主要信号

信号 说明
newConnection() 有新客户端连接
closed() 服务器关闭
acceptError(QAbstractSocket::SocketError) 接受连接出错

4.5 重要枚举

  • QWebSocketProtocol::Version:协议版本(VersionLatest / Version13 等)
  • QWebSocketServer::SslModeNonSecureMode / SecureMode
  • QWebSocketProtocol::CloseCode:关闭码(NormalClosureGoingAway 等)

5. 完整实战示例

下面是一个同时包含客户端与服务器的完整示例,便于快速验证。

5.1 服务器端(main.cpp)

cpp 复制代码
#include <QCoreApplication>
#include <QWebSocketServer>
#include <QWebSocket>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QWebSocketServer server(QStringLiteral("Echo Server"),
                            QWebSocketServer::NonSecureMode);

    QObject::connect(&server, &QWebSocketServer::newConnection, [&server]() {
        QWebSocket *client = server.nextPendingConnection();
        qDebug() << "Client connected:" << client->peerAddress().toString();

        QObject::connect(client, &QWebSocket::textMessageReceived,
                         [client](const QString &msg) {
            qDebug() << "Received:" << msg;
            client->sendTextMessage(QStringLiteral("Echo: ") + msg);
        });

        QObject::connect(client, &QWebSocket::disconnected,
                         client, &QObject::deleteLater);
    });

    if (server.listen(QHostAddress::Any, 1234)) {
        qDebug() << "Server listening on port" << server.serverPort();
    } else {
        qDebug() << "Listen failed";
        return 1;
    }

    return a.exec();
}

5.2 客户端端(main.cpp)

cpp 复制代码
#include <QCoreApplication>
#include <QWebSocket>
#include <QDebug>

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    QWebSocket socket;

    QObject::connect(&socket, &QWebSocket::connected, [&socket]() {
        qDebug() << "Connected, sending message...";
        socket.sendTextMessage(QStringLiteral("Hello, Server!"));
    });

    QObject::connect(&socket, &QWebSocket::textMessageReceived,
                     [](const QString &msg) {
        qDebug() << "Server said:" << msg;
    });

    QObject::connect(&socket, &QWebSocket::disconnected, &a,
                     &QCoreApplication::quit);

    // 连接过程中发生错误
    QObject::connect(&socket, &QWebSocket::errorOccurred, [](QAbstractSocket::SocketError e){
        qDebug() << "Error:" << e;
    });

    socket.open(QUrl(QStringLiteral("ws://localhost:1234")));

    return a.exec();
}

5.3 .pro 文件

pro 复制代码
QT += core websockets
CONFIG += c++17
SOURCES += main.cpp

Qt WebSocket 聊天系统 --- 服务端 + 客户端案例

项目 角色 说明
QWebsocketServerPrs 服务端 消息中转站,监听 8899 端口,管理连接、群发/私发/转发消息
untitled40 客户端 聊天界面,连接服务器、发送/接收消息

两个项目配套使用才能组成一个完整的多人聊天系统。


1. 两个项目是什么关系

复制代码
┌─────────────────────┐        ws://192.168.x.x:8899        ┌─────────────────────┐
│  QWebsocketServerPrs │  ◄──────────────────────────────►  │     untitled40      │
│   (服务端)          │                                    │   (客户端)        │
│   监听 8899 端口      │       可有多个客户端同时连接         │  填写地址+名称连接   │
└─────────────────────┘                                    └─────────────────────┘
QWebsocketServerPrs(服务端) untitled40(客户端)
核心类 QWebSocketServer QWebSocket
数量 1 个 可以开很多个(多个人聊天)
职责 监听端口、管理连接、群发/私发/转发 发起连接、发送消息、接收并显示消息

客户端把"自己的名字"当 origin 传给服务器,服务器靠 socket->origin() 认人、靠 JSON 里的 dst 转发消息。


整体代码仓库地址

HTTPS:https://github.com/wuyongGitHub/qt-websocket-chat.git

SSH:git@github.com:wuyongGitHub/qt-websocket-chat.git

多客户端连接服务端效果

群发消息效果

私发消息效果

客户端相互发消息效果

整体效果:

6. 常见问题与注意事项

根据前端开发业务流,总结一下websocket使用事项

  • 心跳保活 :长时间空闲的连接可能被中间设备断开,建议定期发送 ping(Qt 会自动响应 ping/pong,可手动 ping() 检测存活)。
  • 线程模型QWebSocket 非线程安全,跨线程使用时需通过信号槽或 QMetaObject::invokeMethod 调度到所属线程。
  • 错误处理 :务必连接 errorOccurred 信号,网络异常时才能及时感知并重连。
  • 大文件传输:二进制消息适合传输大块数据,但需注意分帧与内存占用,必要时自行设计分片协议。
  • 安全 :生产环境应使用 wss://SecureMode)并正确配置证书,避免明文传输敏感数据。
  • 释放时机 :客户端断开连接后,服务器端应及时 deleteLater 释放 QWebSocket 对象,防止内存泄漏。
相关推荐
ttwuai26 分钟前
Go 后台附件迁到对象存储后,path、cdnUrl 和 tenant_id 怎么一起验?
开发语言·后端·golang
一只小阿乐31 分钟前
java 语法学习 1
java·开发语言·学习
卢锡荣37 分钟前
Type-C口电子产品离不开的C口逻辑专用控制芯片介绍
c语言·开发语言
顶点多余40 分钟前
算法哪些事儿---2
java·开发语言
方知我42 分钟前
NumPy一小时速成
开发语言·python·numpy
haerapi1 小时前
流式对话接口怎么选:SSE 与 WebSocket 的原理、实现和工程边界
网络·websocket·网络协议
OPEN-F1 小时前
C++综合实战:面向对象图书管理系统
开发语言·c++
ttwuai1 小时前
Go 后台清空操作日志失败,权限和无 WHERE 删除怎么排查?
开发语言·后端·golang
西西弗Sisyphus2 小时前
Qt 在无边框窗口上做一套换肤系统
开发语言·数据库·qt