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

【QT】Qt中Websocket的使用

一、WebSocket的定义

        WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455,并由RFC7936补充规范。WebSocket API也被W3C定为标准。        

        WebSocket使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。想对应http协议来说,websocket更加的平等,在http协议中,只有客户端向服务器发送申请请求之后,服务器才会返回请求的数据,如果要保证实时性的话,就需要不断地轮询,每隔一段时间就向服务器发送一个请求,这样就会造成很大的开销,而WebSocket服务器主动向客户端发送数据,而不需要申请,客户端发送数据给服务器也是如此

        简单来说,就是浏览器和服务器之间通信的一种协议,相比较http来说,数据交换更加平等,开销更小;

二、服务器和客户端

        要想在Qt实现websocket那么我们主要的就是实现一个服务器,由网页实现一个客户端

2.1 服务器的实现

        要实现服务器,首先要认识QWebSocketServer Class,我们需要通过这个类实现

 1)类分析

        从上图可以知道,需要在.pro文件中添加QT+=websockets,然后添加头文件,新建一个WebSocketTest窗口应用程序,试图如下

2)添加库

        在WebSocketTest中添加下面的语句

QT       += websockets

3)添加头文件

        在websockettest.h中添加头文件,声明变量

#ifndef WEBSOCKETTEST_H
#define WEBSOCKETTEST_H#include <QWidget>
#include <QWebSocketServer>QT_BEGIN_NAMESPACE
namespace Ui { class WebSocketTest; }
QT_END_NAMESPACEclass WebSocketTest : public QWidget
{Q_OBJECTpublic:WebSocketTest(QWidget *parent = nullptr);~WebSocketTest();private:Ui::WebSocketTest *ui;//声明QWebSocketServer变量QWebSocketServer *web_server;};
#endif // WEBSOCKETTEST_H

4)QWebSocketServer类的使用

        再来看一看关于这个类的使用,类名上面F1进入帮助界面,可以看到

翻译过来就是

QWebSocketServer是一个基于QTcpServer模型的类,用于处理WebSocket协议的服务器端通信。如果你知道如何使用QTcpServer,你就可以很轻松的使用QWebSocketServer。

QWebSocketServer类主要用于接收并处理来自客户端的WebSocket连接,你可以手动设定服务端的端口,也可以让QWebSocketServer自动选择。调用listen()函数即可让服务器开始侦听连接请求。

每当有新的客户端尝试连接服务器时,newConnection()信号就会发出。服务器可以调用nextPendingConnection()方法接受这个握手请求,同时返回一个已经连接状态的QWebSocket对象指针,服务器即可通过这个指针和客户端进行通信。

如果在过程中发生错误,serverError()方法可以获取错误类型,同时可以调用errorString()方法获取人类可读的错误描述。

当服务器侦听连接请求时,可以通过serverAddress()和serverPort()来获取服务器正在侦听的地址和端口。调用close()函数可以使QWebSocketServer停止侦听连接请求。

QWebSocketServer当前还不支持WebSocket拓展和WebSocket子协议。该类仅支持RFC 6455中规定的WebSocket协议的13版。

有一个默认的握手超时设置为10秒,主要用于防止拒绝服务攻击,该超时时间可以通过setHandshakeTimeout()自定义。

参见WebSocket Server Example和QWebSocket。

        也就是说使用listen函数监听连接请求,一旦有新的客户端连接,就可以触发newConnection()信号,再由服务器通过nextPendingConnection()方法接收这个客户端的连接,这个方法返回一个QWebsocket的对象指针,通过这个指针就可以和客户端通信了

5)代码实现

        首先客户端代码我这里直接提供一个可以测试的html,新建一个文本文件,将下面内容复制进去,保存后,将后缀改为html,点击使用浏览器打开。

<!DOCTYPE html>
<html>
<head>
<title>WebSocket Test</title>
<style>#testButton {display: block;margin: 20px auto;padding: 10px 20px;font-size: 16px;}#messageDisplay {margin: 20px auto;padding: 10px;border: 1px solid #ccc;width: 80%;height: 200px;overflow-y: scroll;font-size: 14px;}
</style>
</head>
<body>
<button id="testButton">Send Test Message</button>
<div id="messageDisplay"></div><script>
var ws = new WebSocket('ws://localhost:15678');ws.onopen = function() {console.log('WebSocket connection opened.');
};ws.onmessage = function(event) {console.log('Message from server:', event.data);var messageDisplay = document.getElementById('messageDisplay');messageDisplay.innerHTML += '<p>' + event.data + '</p>';
};ws.onerror = function(error) {console.error('WebSocket error:', error);
};ws.onclose = function() {console.log('WebSocket connection closed.');
};document.getElementById('testButton').onclick = function() {ws.send('Test');console.log('Test message sent.');
};
</script>
</body>
</html>

服务器相关代码

构造函数

 web_server = new QWebSocketServer("Myserver",QWebSocketServer::NonSecureMode,this);if(web_server->listen(QHostAddress::Any,15678)){qDebug()<<"开始监听";connect(web_server,&QWebSocketServer::newConnection,this,&WebSocketTest::newCilentConnect);}

槽函数

void WebSocketTest::newCilentConnect()
{//返回客户端web_client = web_server->nextPendingConnection();qDebug() << "有新的 WebSocket 客户端连接。";}

编译运行服务器,然后点击html文件,可以发现会打印”有新的 WebSocket 客户端连接“;

6)接收客户端的消息

void WebSocketTest::newCilentConnect()
{//返回客户端web_client = web_server->nextPendingConnection();qDebug() << "有新的 WebSocket 客户端连接。";// 处理接收到的消息connect(web_client , &QWebSocket::textMessageReceived, this, &WebSocketTest::onTextMessageReceived);}void WebSocketTest::onTextMessageReceived(const QString &message)
{qDebug() << "收到客户端消息:" << message;if(message=="Test"){/*在这里执行你实现的操作,如网页一个按钮,点击后发送打开摄像头信息给服务器,服务器执行打开摄像头的操作*/}
}

        编译运行,点击网页上的按钮,服务器就可以收到这个消息了;

2.2 客户端的实现

        到前面为止就可以实现客户端发送数据到服务器的操作,现在实现服务器发送数据给客户端


// 向客户端发送数据
void WebSocketTest::sendClientData(const QString &str)
{if (web_client->isValid()) {web_client->sendTextMessage(str);}
}

然后在界面上添加一个按钮发送信息给客户端


void WebSocketTest::on_btn_send_clicked()
{sendClientData("Hello");
}

编译运行,刷新网页后,点击按钮查看效果

 三、完整源码

websocket.c

#include "websockettest.h"
#include "ui_websockettest.h"WebSocketTest::WebSocketTest(QWidget *parent): QWidget(parent), ui(new Ui::WebSocketTest)
{ui->setupUi(this);// 创建 WebSocket 服务器web_server = new QWebSocketServer("Myserver",QWebSocketServer::NonSecureMode,this);//监听if(web_server->listen(QHostAddress::Any,15678)){qDebug()<<"开始监听";connect(web_server,&QWebSocketServer::newConnection,this,&WebSocketTest::newCilentConnect);}}void WebSocketTest::newCilentConnect()
{web_client = web_server->nextPendingConnection();qDebug() << "有新的 WebSocket 客户端连接。";// 处理客户端断开连接connect(web_client, &QWebSocket::disconnected, this, [this, web_client]() {qDebug() << "WebSocket 客户端断开连接。";web_client->deleteLater();});// 处理接收到的消息connect(web_client, &QWebSocket::textMessageReceived, this, &WebSocketTest::onTextMessageReceived);}
void WebSocketTest::onTextMessageReceived(const QString &message)
{qDebug() << "收到客户端消息:" << message;}// 向客户端发送数据
void WebSocketTest::sendClientData(const QString &str)
{if (web_client->isValid()) {web_client->sendTextMessage(str);}
}void WebSocketTest::on_btn_send_clicked()
{sendClientData("Hello");
}WebSocketTest::~WebSocketTest()
{delete ui;
}

websocket.h

#ifndef WEBSOCKETTEST_H
#define WEBSOCKETTEST_H#include <QWidget>
#include <QWebSocketServer>
#include <QDebug>
#include <QWebSocket>QT_BEGIN_NAMESPACE
namespace Ui { class WebSocketTest; }
QT_END_NAMESPACEclass WebSocketTest : public QWidget
{Q_OBJECTpublic:WebSocketTest(QWidget *parent = nullptr);~WebSocketTest();private:Ui::WebSocketTest *ui;//声明QWebSocketServer变量  服务器QWebSocketServer *web_server;//客户端QWebSocket* web_client;private slots://客户端连接槽函数void newCilentConnect();//接收新客户端消息函数void onTextMessageReceived(const QString &message);//发送消息给客户端函数void on_btn_send_clicked();private://发送消息给客户端void sendClientData(const QString &str);};
#endif // WEBSOCKETTEST_H

websocket.html

<!DOCTYPE html>
<html>
<head>
<title>WebSocket Test</title>
<style>#testButton {display: block;margin: 20px auto;padding: 10px 20px;font-size: 16px;}#messageDisplay {margin: 20px auto;padding: 10px;border: 1px solid #ccc;width: 80%;height: 200px;overflow-y: scroll;font-size: 14px;}
</style>
</head>
<body>
<button id="testButton">Send Test Message</button>
<div id="messageDisplay"></div><script>
var ws = new WebSocket('ws://localhost:15678');ws.onopen = function() {console.log('WebSocket connection opened.');
};ws.onmessage = function(event) {console.log('Message from server:', event.data);var messageDisplay = document.getElementById('messageDisplay');messageDisplay.innerHTML += '<p>' + event.data + '</p>';
};ws.onerror = function(error) {console.error('WebSocket error:', error);
};ws.onclose = function() {console.log('WebSocket connection closed.');
};document.getElementById('testButton').onclick = function() {ws.send('Test');console.log('Test message sent.');
};
</script>
</body>
</html>

相关文章:

【QT】Qt中Websocket的使用

一、WebSocket的定义 WebSocket是一种在单个TCP连接上进行全双工通信的协议。WebSocket通信协议于2011年被IETF定为标准RFC 6455&#xff0c;并由RFC7936补充规范。WebSocket API也被W3C定为标准。 WebSocket使得客户端和服务器之间的数据交换变得更加简单&#xff0c;…...

【vue3】【elementPlus】【国际化】

1.如需从0-1开始&#xff0c;请参考 https://blog.csdn.net/Timeguys/article/details/140995569 2.使用 vue-i18n 模块&#xff1a; npm i vue-i18n3.在 src 目录下创建 locales 目录&#xff0c;里面创建文件&#xff1a;en.js、zh-cn.js、index.js 语言js文件&#xff1a;…...

用python实现求两个整数的最大公约数

def gcd(a, b): """计算最大公约数""" while b: a, b b, a % b return abs(a) 下面是对 gcd 函数的逐行解释&#xff1a; def gcd(a, b):"""计算最大公约数"""定义函数&#xff1a;这里定义了一个名为 gcd…...

Linux 内核源码分析---proc 文件系统

proc文件系统 进程数据文件系统&#xff08;process data filesystem, procfs&#xff09;装载在 /proc&#xff0c;缩写为 procFS。 proc 文件系统是一种虚拟文件系统&#xff0c;其信息不能从块设备读取。只有在读取文件内容时才动态生成相应的信息。使用proc文件系统&…...

视频号直播回放怎么下载?

一、如果是下载自己直播回放视频&#xff1a; 方法一&#xff1a;视频号助手 打开网址&#xff1a;视频号助手 登陆账号后。下面路径&#xff0c;先点击成回放&#xff0c; 后就可以在下面路径&#xff0c;下载全场回放 但是这种有个缺点&#xff0c;就是不能分段下载。这样…...

【第九节】python中xml解析和json编解码

目录 一、Python XML 解析 1.1 什么是XML 1.2 Python 对 XML 的解析方法 1.3 SAX解析xml 1.4 xml.dom解析xml 1.6 ElementTree解析XML 二、Python编解码json 2.1 什么是json 2.2 使用json 库 2.3 使用第三方库Demjson 一、Python XML 解析 1.1 什么是XML XML&#x…...

yolo v8部署到云服务器问题记录

环境安装 1、运行项目报错&#xff1a;no python application found, check your startup logs for errors 在云服务器pytorch版本安装错了&#xff0c;安装了GPU版本&#xff0c;需要安装CPU版本 # CPU only 使用下面这段代码避免出现第二个错误 pip install torch2.3.1 to…...

端口被占用,杀死进程的步骤

一、 查看所有进程占用的端口 在开始-运行-cmd,输入&#xff1a;netstat –ano可以查看所有进程 二、查看占用指定端口的程序 查看被那个端口占用&#xff0c;可以用该命令&#xff1a; 三、使用命令杀死进程 杀死进程&#xff0c;使用命令&#xff1a;...

接口入门(企业常见使用,一分钟搞定版)

目录 1、接口的定义 定义位置 接口内容 2、接口的使用 正常实现接口 接口当做函数参数 匿名实现接口 3、OPPO便签接口具体分析 总结一下&#xff1a; 1、接口的定义 定义位置 可以写在类中&#xff0c;但注意现在接口名字是 类名.接口名 可以单独写在一个文件 接口内…...

深入解析:Cookie 与 Session 的区别及应用场景

引言 在Web开发中&#xff0c;Cookie 和 Session 是两种常用的用户状态管理机制。虽然它们的目标都是在无状态的HTTP协议中维护用户的状态&#xff0c;但它们的工作原理和适用场景却有所不同。在本文中&#xff0c;我们将深入探讨 Cookie 和 Session 的区别&#xff0c;并通过…...

LLM金融文本分类文档说明

Python注意事项&#xff1a; 1&#xff0c;创建虚拟环境&#xff1a; conda create --prefixD:\software\Anaconda3\envs\finance_analysis python3.10.4 conda create -p D:/software/anaconda3/envs/finance_analysis python3.10.4 注释&#xff1a; D:\software\anaconda3\e…...

EI检索,2天录用,3天见刊!截稿在即,这本水刊你还不投吗?

点击关注&#xff1a;关注GZH【欧亚科睿学术】&#xff0c;GET完整版2023JCR分区列表&#xff01; &#x1f389; &#x1f389; &#x1f389; &#x1f389; 恭喜&#xff01;这本毕业水刊仅2天录用&#xff01;3天见刊&#xff01; 重要时间节点如下 2024-08-03 Sub…...

sql获取过去的小时数

TIMESTAMPDIFF(HOUR, create_time, NOW()) AS pastHours 是一条 SQL 语句的一部分&#xff0c;它使用 TIMESTAMPDIFF 函数来计算两个时间点之间的差异&#xff0c;并将结果标记为 pastHours。 让我们详细解析一下这条语句&#xff1a; TIMESTAMPDIFF 函数: 这个函数用于计算两…...

【Android Studio】彻底卸载

文章目录 卸载程序控制面板卸载安全软件卸载 重启计算机删除文件重启计算机 我们在Android开发时涉及重装时&#xff0c;如果卸载不干净&#xff0c;再次安装是不会正常运行项目的&#xff0c;接下来就让我教你如何删除干净吧。 卸载程序 控制面板卸载 control控制面板一>…...

美术版权可以当做商标使用吗

美术版权与商标的区别及不可混用性分析 在知识产权领域&#xff0c;美术版权和商标权是两个重要的概念&#xff0c;它们各自承载着不同的法律意义和保护范围。 美术版权概述 美术版权&#xff0c;又称著作权&#xff0c;是指著作权人对其创作的美术作品所享有的权利。这些作品…...

控制某些请求不记录日志

说明&#xff1a;由于统一拦截日志请求&#xff0c;导致所有匹配的请求都会打印日志&#xff0c;这里需要控制有些请求执行不打印日志&#xff0c;比如定时每隔几秒执行某些请求。 具体实现如下&#xff1a; 一、自定义注解&#xff0c;如下&#xff1a; /** * Description: …...

Java线程池原理剖析和应用指南

目录 Java线程池详解一、Java线程池简介池化思想池化思想的优点 二、线程池的实现原理分析实现线程池需要考虑哪些问题&#xff1f;线程池的简单使用示例线程池原理的简单图示 三、Executor详解Executor简介Executor框架的继承结构总结ExecutorExecutorService 四、ThreadPoolE…...

ST-LINK烧录MCU

打开ST-LINK软件&#xff1a; 主板断电状态下接入烧录器&#xff0c;烧录器USB连接电脑&#xff1a; 主板上电&#xff0c;点击连接按钮&#xff1a; 点击加载文件&#xff1a; 点击写入按钮&#xff0c;烧录成功后拔掉烧录器&#xff0c;主板重新上电...

Go - 10. * 值类型和指针类型的差异

目录 一.引言 二.接收者类型 三.代码示例 1.指针接收者 2.值接收者 3.运行结果对比 4.代码修改 5.刨根问底 四.总结 一.引言 go 语言中 func (c *Title) 和 func (c Title) 两个方法的传参差一个 * 号&#xff0c;二者的区别是一个是指针类型&#xff0c;一个是值类型…...

waf绕过:网络安全狗绕过

引言&#xff1a; 所有的绕过原理都大致一致&#xff0c;但是并不是所有的绕过都能起到作用&#xff0c;渗透测试主要还是一个猜加试的过程&#xff0c;本文仅供参考 网络攻击或扫描绕过 1.get绕过&#xff08;未开启cc防护&#xff09; 网络安全狗的默认防护为&#xff0c;拒…...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台&#xff0c;以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中&#xff0c;Producer&#xff08;生产者&#xff09; 是连接客户端应用与消息队列的第一步。生产者…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

3403. 从盒子中找出字典序最大的字符串 I

3403. 从盒子中找出字典序最大的字符串 I 题目链接&#xff1a;3403. 从盒子中找出字典序最大的字符串 I 代码如下&#xff1a; class Solution { public:string answerString(string word, int numFriends) {if (numFriends 1) {return word;}string res;for (int i 0;i &…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

C++.OpenGL (20/64)混合(Blending)

混合(Blending) 透明效果核心原理 #mermaid-svg-SWG0UzVfJms7Sm3e {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-icon{fill:#552222;}#mermaid-svg-SWG0UzVfJms7Sm3e .error-text{fill…...

Python+ZeroMQ实战:智能车辆状态监控与模拟模式自动切换

目录 关键点 技术实现1 技术实现2 摘要&#xff1a; 本文将介绍如何利用Python和ZeroMQ消息队列构建一个智能车辆状态监控系统。系统能够根据时间策略自动切换驾驶模式&#xff08;自动驾驶、人工驾驶、远程驾驶、主动安全&#xff09;&#xff0c;并通过实时消息推送更新车…...