首页 > 其他分享 >【QT】Qt中Websocket的使用

【QT】Qt中Websocket的使用

时间:2024-08-07 17:53:56浏览次数:10  
标签:web WebSocket QT WebSocketTest 服务器 Websocket Qt QWebSocketServer 客户端

一、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_NAMESPACE

class WebSocketTest : public QWidget
{
    Q_OBJECT

public:
    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_NAMESPACE

class WebSocketTest : public QWidget
{
    Q_OBJECT

public:
    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>

标签:web,WebSocket,QT,WebSocketTest,服务器,Websocket,Qt,QWebSocketServer,客户端
From: https://blog.csdn.net/weixin_62370184/article/details/140994642

相关文章

  • QStyledItemDelegate 和QTreeView实现鼠标hover消息
    1.QTreeView设置属性mousetracking和tablettracing 重写QStyledItemDelegate类,重写函数booleditorEvent(QEvent*event,QAbstractItemModel*model,constQStyleOptionViewItem&option,constQModelIndex&index);这个函数里可以处理鼠标hover和点击事件;boolTreeTas......
  • UE Websocket 通信
    项目中遇到UE需要对接Websocket协议接收实时数据。所以需要实现一个WebsocketClient的功能。由于UE引擎已经集成了Websocket库(基于libwebsocket),可以通过集成的WebSocket库来比较难容易实现WebSocketClient和Server进行通信。编程实现(C++)需要使用C++语言进行编程。下面是相......
  • qt的项目结构
    创建新的项目下一步下一步下一步 下一步 第一个hell0程序,qt的项目结构创建顶目的时候Qwidget、OMainWindow、ODialog是所有能看到的窗口或者控件的父类,OMainWindow、ODialog都继承自它main函数QApplication就是EQT里边每个应用程序有且仅有一个的应用程序对象......
  • linux与windows环境下qt程序打包教程
    一、演示环境qt5.14.2二、Linux2.1关联依赖文件2.1.1下载打包工具在Windows环境下可以使用QtCreator自带的官方工具进行打包,而Linux环境下没有官方工具,需要借助第三方工具才能打包。如:linuxdeployqt、CQtDeployer、AppImageKit,甚至是自己编写shell将依赖导入指定目录......
  • VTK8.0.0编译(Qt 5.14.2+VS2017)
    VTK8.0.0编译(Qt5.14.2+VS2017)本片文章编译VTK8.0.0主要是为了配合PCL1.8.1而编译的,因为PCL1.8.1使用的是VTK8.0版本,但是PCL安装文件夹中提供的VTK8.0不全,和Qt结合使用的时候,会报错。所以还是得自己重新编译。关于Qt和MSVC的安装,可以参考文章(Qt5.14安装(配置MSVC2017))。......
  • QT解析读取XML文件并显示在列表视图里
      背景:本地用数据库管理用户数据不方便,需要手动增删查改账户,存在安全风险,两个方案可供替代:1.调用接口来获取用户信息json,通过软件解析json字符串提取用户账号信息。2.直接跳过调用接口那一步,选择xml文件路径并解析。(由于第一种方案行不通,故使用第二种)步骤一:界面设计添加一......
  • Qt | QScatterSeries 散点图
    点击上方"蓝字"关注我们01、QScatterSeries QScatterSeries 的类,它将代表散点图中的一个系列。这个类将包含数据点、颜色和样式等属性,以及用于绘制散点图的方法。02、main.cpp#include<QtWidgets/QApplication>#include<QtWidgets/QMainWindow>#include"chartview.h"......
  • rqt的安装及详细介绍
    1.安装安装极其简单,不多介绍,直接上命令:Melodic: sudoapt-getinstallros-melodic-rqtsudoapt-getinstallros-melodic-rqt-common-pluginsNoetic sudoapt-getinstallros-noetic-rqtsudoapt-getinstallros-noetic-rqt-common-plugins2.部分工具的功能介......
  • Qt/C++最新地图组件发布/历时半年重构/同时支持各种地图内核/包括百度高德腾讯天地图
    一、前言说明最近花了半年时间,专门重构了整个地图组件,之前写的比较粗糙,有点为了完成功能而做的,没有考虑太多拓展性和易用性。这套地图自检这几年大量的实际项目和用户使用下来,反馈了不少很好的建议和意见,经过这几年的整理,刚好趁着近期经济下行严重,抽出时间把整个地图组件重构一下......
  • Linux系统打包Qt
    因为使用了QWebEngineView,所以遇到了打包问题,记录一下我的失败过程。等以后有机会再接着弄吧目前知道的打包方式有三种:1.linuxdeplot+linuxdeploy-plugin-qt2.linuxdeplotqt+appimagetool3.使用脚本,收集ldd显示的依赖库 第一种(linuxdeplot+linuxdeploy-plugin-qt),......