当前位置: 首页 > news >正文

Qt-HTTPWebSocket

一、 HTTP 核心语法与作用

核心类

QNetworkAccessManager - 管理所有网络请求
QNetworkRequest - 配置请求参数和头部
QNetworkReply - 处理服务器响应数据

请求方法

manager.get(request) - 发送GET请求获取数据manager.post(request, data) - 发送POST请求提交数据manager.put(request, data) - 发送PUT请求更新数据manager.deleteResource(request) - 发送DELETE请求删除数据

请求配置

request.setUrl(url) - 设置请求URLrequest.setRawHeader(name, value) - 设置自定义请求头request.setHeader(type, value) - 设置标准请求头request.setTransferTimeout(ms) - 设置请求超时时间

响应处理

reply.readAll() - 读取所有响应数据reply.error() - 获取错误代码reply.errorString() - 获取错误描述reply.attribute(attr) - 获取响应属性(如状态码)

信号连接

reply.finished() - 请求完成信号reply.downloadProgress() - 下载进度信号reply.uploadProgress() - 上传进度信号reply.errorOccurred() - 错误发生信号

内存管理

reply.deleteLater() - 安全删除回复对象reply.abort() - 中止进行中的请求

案例

获取百度网站的信息:
mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QMutex>
#include <QtNetwork>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_clicked();void finshandshowdata(QNetworkReply *reply);private:Ui::MainWindow *ui;QNetworkAccessManager *manage;};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QMutex>
#include <QDebug>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);manage=new QNetworkAccessManager(this);connect(manage, &QNetworkAccessManager::finished, this, &MainWindow::finshandshowdata);connect(ui->pushButton,&QPushButton::clicked,this,&MainWindow::on_pushButton_clicked);}MainWindow::~MainWindow()
{manage->disconnect();delete ui;
}void MainWindow::finshandshowdata(QNetworkReply *reply)
{if (reply->error() == QNetworkReply::NoError) {ui->textBrowser->setText(reply->readAll());} else {ui->textBrowser->setText("错误: " + reply->errorString());}reply->deleteLater();  // 重要:删除reply对象
}
void MainWindow::on_pushButton_clicked()
{QNetworkRequest request(QUrl("https://www.baidu.com/"));manage->get(request);// 发送GET请求}

这里注意一下connect的方式,逻辑为点击按钮发送请求,QNetworkAccessManager 类的对象manage会管理这个请求,完成后会触发显示的函数。

二、WebSocket

概述

WebSocket是一种在单个TCP连接上进行全双工通信的协议,它允许服务端主动向客户端推送数据,适合实时应用。

核心类:

类名功能描述主要用途
QWebSocketServerWebSocket 服务器监听客户端连接,处理握手,管理连接
QWebSocketWebSocket 客户端连接到服务器,并与服务器进行双向数据交换

🔧 服务器端核心用法

使用 QWebSocketServer 构建服务器的步骤通常如下:

创建服务器实例:需要指定服务器名称和安全模式。

cpp

// 安全模式 (wss): QWebSocketServer::SecureMode
// 非安全模式 (ws): QWebSocketServer::NonSecureMode
QWebSocketServer *server = new QWebSocketServer("My Server", QWebSocketServer::NonSecureMode, this);

监听连接:绑定地址和端口以开始监听。

cpp

server->listen(QHostAddress::Any, 12345)

处理新连接:连接 newConnection 信号,在槽函数中接受连接。

cpp

connect(server, &QWebSocketServer::newConnection, this, [this, server]() {QWebSocket *clientSocket = server->nextPendingConnection();if (clientSocket) {// 成功获取客户端连接,可以进行进一步设置// 例如:连接 clientSocket 的各种信号以处理数据和连接状态}
});

​​​​​​与客户端通信:通过获取到的 QWebSocket 对象与客户端交互。

cpp

connect(clientSocket, &QWebSocket::textMessageReceived, this, &MyClass::onTextMessageReceived);

发送消息

发送文本消息:clientSocket->sendTextMessage("Hello from server!");

发送二进制消息:clientSocket->sendBinaryMessage(QByteArray::fromHex("..."))

接收消息:连接 textMessageReceived 或 binaryMessageReceived 信号。

关闭连接:在适当的时候关闭客户端连接或服务器。

cpp

clientSocket->close(); // 关闭单个客户端连接
server->close();       // 关闭服务器,停止监听

📡 客户端核心用法

在 C++ 中使用 QWebSocket 客户端:

创建客户端并连接

cpp

QWebSocket *webSocket = new QWebSocket;
connect(webSocket, &QWebSocket::connected, this, []() {qDebug() << "Connected to server!";
});
connect(webSocket, &QWebSocket::textMessageReceived, this, [](const QString &message) {qDebug() << "Message from server:" << message;
});

 处理连接状态

// 连接状态信号
connect(webSocket, &QWebSocket::connected, this, [this]() {// 连接建立时的处理
});connect(webSocket, &QWebSocket::disconnected, this, [this]() {// 连接断开时的处理
});// 错误处理
connect(webSocket, &QWebSocket::errorOccurred, this, [this](QAbstractSocket::SocketError error) {// 错误处理
});// 状态变化
connect(webSocket, &QWebSocket::stateChanged, this, [this](QAbstractSocket::SocketState state) {// 状态变化处理
});

发送消息

cpp

webSocket->sendTextMessage("Hello from client!");

案例

一个服务器端和多个客户端之间以及客户端之间的通信案例。

服务器端逻辑

.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QWebSocket>//客户端
#include<QWebSocketServer>//服务器端
#include<QJsonDocument>//json
#include<QJsonObject>//json对象
#include <QAbstractSocket>  // 用于 SocketError 枚举QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();
QWebSocketServer *websocketserver;
QList<QWebSocket*> websocketlist;//存储连接到服务器的客户端列表
void getnewconnect();
void receiveMsg(const QString &msg);
void handleClientDisconnected(QWebSocket *websocket);
public slots:
void onerrorFunc(QAbstractSocket::SocketError error);
private slots:void on_pushButton_send_clicked();private:Ui::MainWindow *ui;};
#endif // MAINWINDOW_H

.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);websocketserver=new QWebSocketServer(QStringLiteral("testServer"),QWebSocketServer::NonSecureMode,this);connect(websocketserver,&QWebSocketServer::newConnection,this,&MainWindow::getnewconnect);websocketserver->listen(QHostAddress::Any,8899);}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::getnewconnect()
{QWebSocket *websocket=websocketserver->nextPendingConnection();//获取新的客户端连接ui->show->append(websocket->origin()+"客户端已连接到服务器");//显示连接信息websocketlist<<websocket;//将连接的客户端添加到连接列表QListWidgetItem *item=new QListWidgetItem;item->setText(websocket->origin());ui->listWidget_client->addItem(item);//将连接的客户端添加到客户端列表connect(websocket,&QWebSocket::disconnected,this, [this, websocket]() {handleClientDisconnected(websocket);});//设置断开连接的处理逻辑connect(websocket,&QWebSocket::textMessageReceived,this,&MainWindow::receiveMsg);connect(websocket, &QWebSocket::errorOccurred,this, &MainWindow::onerrorFunc);
}
void MainWindow::handleClientDisconnected(QWebSocket *websocket)
{ui->show->append(websocket->origin() + "客户端已断开服务器");websocketlist.removeOne(websocket);for(int i = 0; i < ui->listWidget_client->count(); i++){QListWidgetItem *item = ui->listWidget_client->item(i);QWebSocket *itemSocket = item->data(Qt::UserRole).value<QWebSocket*>();if(itemSocket == websocket){delete ui->listWidget_client->takeItem(i);  // 正确的删除方式break;}}websocket->deleteLater();
}
void MainWindow::receiveMsg(const QString &msg)
{// 获取发送消息的客户端QWebSocket *senderSocket = qobject_cast<QWebSocket*>(sender());if (!senderSocket) {ui->show->append("错误:无法获取发送者信息");return;}QString senderName = senderSocket->origin();ui->show->append("收到来自[" + senderName + "]的消息: " + msg);QJsonDocument jd = QJsonDocument::fromJson(msg.toUtf8());if(jd.isNull()){// 普通文本消息 - 广播给所有客户端for(auto client : websocketlist) {if(client != senderSocket) {client->sendTextMessage(msg);}}ui->show->append("广播消息给所有客户端");}else{// JSON格式消息 - 定向发送QJsonObject jbo = jd.object();ui->show->append("解析结果 - 源: " + jbo["src"].toString() + ", 目标: " + jbo["dst"].toString() + ", 消息: " + jbo["msg"].toString());if(jbo["dst"].toString().isEmpty()) {ui->show->append("错误:目标客户端为空,无法转发");return;}// 查找目标客户端bool found = false;QString dstClient = jbo["dst"].toString();QString messageContent = jbo["msg"].toString();QString srcClient = jbo["src"].toString();for(auto client : websocketlist) {if(client->origin() == dstClient) {// 创建新的消息格式,只发送内容和来源QJsonObject forwardMsg;forwardMsg["src"] = srcClient;      // 原始发送者forwardMsg["msg"] = messageContent; // 消息内容forwardMsg["type"] = "forward";     // 消息类型标识QString forwardJson = QString(QJsonDocument(forwardMsg).toJson(QJsonDocument::Compact));client->sendTextMessage(forwardJson);ui->show->append("成功转发消息给: " + dstClient);found = true;break;}}if(!found) {ui->show->append("错误:未找到目标客户端: " + jbo["dst"].toString());QStringList clientNames;for(auto client : websocketlist) {clientNames.append(client->origin());}ui->show->append("当前连接的客户端: " + clientNames.join(", "));}}}void MainWindow::onerrorFunc(QAbstractSocket::SocketError error)
{QWebSocket *websocket = qobject_cast<QWebSocket*>(sender());ui->show->append(websocket->origin()+"出错"+websocket->errorString());
}void MainWindow::on_pushButton_send_clicked()
{QString text=ui->textEdit_send->toPlainText().trimmed();if(text.isEmpty()){return;}if(ui->radioButton_group->isChecked())//群发客户端{if(websocketlist.size()==0){return;}for(auto it=websocketlist.begin();it!=websocketlist.end();it++){QWebSocket *client = *it;client->sendTextMessage(text);}}else{if(!ui->listWidget_client->currentItem()){return;}QString strcurrent=ui->listWidget_client->currentItem()->text();QWebSocket *websocket=nullptr;for(auto it=websocketlist.begin();it!=websocketlist.end();it++){QWebSocket *client = *it; // 解引用迭代器获取实际的 WebSocket 指针if(client->origin()==strcurrent){websocket=client;break;}}if(websocket){websocket->sendTextMessage(text);ui->textEdit_send->append("服务端给["+websocket->origin()+"]发送--->"+strcurrent);}}ui->textEdit_send->clear();
}

客户端逻辑

.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QWebSocket>
#include<QJsonDocument>
#include<QJsonObject>
#include<QMessageBox>
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_link_clicked();void on_pushButton_send_clicked();private:Ui::MainWindow *ui;QWebSocket *websocket;bool bconnect=false;void receviedMsg(const QString &msg);void onerror(QAbstractSocket::SocketError error);};
#endif // MAINWINDOW_H

.cpp

#include "mainwindow.h"
#include "./ui_mainwindow.h"MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);websocket=nullptr;
}MainWindow::~MainWindow()
{delete ui;if(websocket){websocket->close();}
}
void MainWindow::receviedMsg(const QString &msg)
{QJsonDocument jsd = QJsonDocument::fromJson(msg.toUtf8()); // 直接使用 toUtf8()if(jsd.isNull()) {ui->textBrowser_show->append("收到消息:" + msg);} else {QJsonObject hsobj = jsd.object();ui->textBrowser_show->append("收到来自" + hsobj["src"].toString() + "的消息:" + hsobj["msg"].toString());}
}
void MainWindow::onerror(QAbstractSocket::SocketError error)
{ui->textBrowser_show->append(websocket->origin()+"出错"+websocket->errorString());//显示错误信息和错误描述
}void MainWindow::on_pushButton_link_clicked()
{if(!websocket)//如果Websocket不存在(需要建立连接){// 创建WebSocket连接if(ui->lineEdit_name->text().trimmed().isEmpty())//验证服务器名称是否为空{QMessageBox::critical(this,"错误","服务器名称不能为空",QMessageBox::Yes);return;}if(ui->lineEdit_ip->text().trimmed().isEmpty())//验证服务器地址是否为空{QMessageBox::critical(this,"错误","服务器地址不能为空",QMessageBox::Yes);return;}//创建WebSocket对象websocket = new QWebSocket(ui->lineEdit_name->text().trimmed(), QWebSocketProtocol::VersionLatest, this);//连接成功信号槽,更新UI状态connect(websocket, &QWebSocket::connected, this, [this]{ui->textBrowser_show->append("已连接上" + websocket->peerAddress().toString());bconnect = true;//设置连接状态ui->pushButton_link->setText("断开服务器");//更新按钮文本});//断开连接信号槽,更新UI状态connect(websocket, &QWebSocket::disconnected, this, [this]{ui->textBrowser_show->append("已断开连接");bconnect = false;ui->pushButton_link->setText("连接服务器");});connect(websocket, &QWebSocket::errorOccurred, this, &MainWindow::onerror);connect(websocket, &QWebSocket::textMessageReceived, this, &MainWindow::receviedMsg);// 使用正确的服务器地址QString url = ui->lineEdit_ip->text().trimmed();// 确保URL有协议前缀if(!url.startsWith("ws://") && !url.startsWith("wss://")) {url = "ws://" + url;}//打开WebSocket连接websocket->open(QUrl(url));}else//如果WebSocket已存在(需要断开连接){// 断开连接websocket->close();websocket->deleteLater();websocket = nullptr;bconnect = false;ui->pushButton_link->setText("连接服务器");}
}void MainWindow::on_pushButton_send_clicked()
{if(!websocket||!websocket->isValid()){//检查WebSocket连接是否有效return;}QString text=ui->textEdit_send->toPlainText().trimmed();//获取要发送的文本内容if(text.isEmpty()){  return;}//检查是否为空QString client=ui->lineEdit_client_name->text().trimmed();//获取客户端名称if(client.isEmpty()){websocket->sendTextMessage(text);ui->textBrowser_show->append("发送消息:"+text);}else{QJsonObject jsobj;jsobj["src"]=websocket->origin();jsobj["dst"]=client;jsobj["msg"]=text;websocket->sendTextMessage(QString(QJsonDocument(jsobj).toJson(QJsonDocument::Compact)));ui->textBrowser_show->append("给另一个客户端"+client+"发送消息"+text);}ui->textEdit_send->clear();
}

结果:
服务器端和多个客户端通信

群发:

私发(在服务器右边选中):

通过服务器转发使两个客户端聊天:

http://www.dtcms.com/a/552912.html

相关文章:

  • MATLABcode|2个雷达二维目标跟踪滤波系统 - EKF实现,匀速运动模型,输入:雷达观测数据(距离、方位角),输出:目标状态估计(位置、速度)
  • TDengine 数据函数 CORR 用户手册
  • Java的驼峰转换实现方案
  • 从零开始的C++学习生活 19:C++复习课(5.4w字全解析)
  • 阿里云-云服务器的创建与使用
  • 安防监控系统:安防之眼,智守未来
  • 网站建设吸引人的话语广元北京网站建设
  • 网站上线前营销推广工作准备网站创建费用
  • Apache Tomcat RewriteValve目录遍历漏洞 | CVE-2025-55752 复现
  • k8s:service资源详解
  • 大型系统性能优化问题
  • 国际版多语言语聊语音厅交友源码开发:技术特性、中外差异与核心注意事项
  • 面对网络蠕虫的紧急处理方式和防护措施
  • 深入掌握 Maven Settings:从配置到实战
  • 厦门做网站seo的惠州哪家做网站比较好
  • 目标检测原理分享
  • AI驱动的VSCode插件开发:从模型研发到性能优化的全栈实践
  • 6 种无误的方法:如何备份和恢复华为手机
  • Spring Boot 整合 ShedLock 处理定时任务重复
  • 静态网站开发课程相关新闻做设计图的网站
  • MCU(微控制器单元)上的语音识别
  • 【普中Hi3861开发攻略--基于鸿蒙OS】-- 第 31 章 WIFI 实验-华为 IoTDA 设备接入
  • hive的全连接
  • 集团企业网站设计方案专业做化学招聘的网站有哪些
  • win11 wsl安装Ubuntu-22.04并迁移D盘 以及安装docker
  • 频闪拍照中的相机和光源同步问题
  • 乐吾乐3D可视化案例【智慧汽车三维可视化】
  • 网站图片验证码出不来潜江资讯网电脑版
  • 大模型在百度电商机审应用的落地实践
  • esp8266+dht11传感器实时上报温湿度