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::SslMode:NonSecureMode/SecureModeQWebSocketProtocol::CloseCode:关闭码(NormalClosure、GoingAway等)
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对象,防止内存泄漏。