【QT进阶】Qt http编程之实现websocket server服务器端

往期回顾

【QT进阶】Qt http编程之json解析的简单介绍-CSDN博客

【QT进阶】Qt http编程之nlohmann json库使用的简单介绍-CSDN博客

【QT进阶】Qt http编程之websocket的简单介绍-CSDN博客

 【QT进阶】Qt http编程之实现websocket server服务器端

一、最终效果

通过ip地址和端口号,我可以开启服务去连接客户端并发送消息

 二、套接字(补充一个知识点)

1、什么是套接字

套接字(Socket)是在计算机网络编程中用于实现网络通信的一种机制。它是网络通信的端点,可以用于在不同计算机之间或同一台计算机的不同进程之间进行数据传输。通过套接字编程,程序可以实现各种网络应用,实现计算机之间的数据交换和通信。

2、套接字类型

流套接字(StreamSocket):

基于TCP协议的套接字类型,提供面向连接的、可靠的、双向的数据流传输。适用于需要可靠传输和顺序数据传输的场景,如HTTP、FTP等应用。

数据报套接字(DatagramSocket):

基于UDP协议的套接字类型,提供无连接、不可靠的数据报传输。适用于需要快速传输但不需要可靠性的场景,如DNS、实时视频传输等。

3、套接字通信过程: 

创建套接字:在应用程序中创建套接字对象,指定协议类型、地址族等参数。
绑定套接字:将套接字绑定到一个特定的IP地址和端口号,以便其他计算机或进程可以通过该地址与之通信。
监听连接:对于服务器端套接字,调用listen()函数开始监听客户端连接请求。
接受连接:对于服务器端套接字,调用accept()函数接受客户端的连接请求,返回一个新的套接字用于与客户端通信。
建立连接:对于客户端套接字,调用connect()函数向服务器发起连接请求,建立与服务器的连接。
数据传输:通过套接字的读写操作(如send()、recv())进行数据传输,实现通信功能。
关闭套接字:通信结束后,调用close()或类似函数关闭套接字,释放资源。

4、套接字编程: 

在网络编程中,套接字通常由操作系统提供的网络库(如Socket API)来实现。

套接字编程可以使用不同的编程语言和平台实现,如C/C++、Python、Java等。

我们可以通过套接字编程实现各种网络通信应用,包括客户端-服务器模型、P2P通信、实时数据传输等。

三、基于Qt框架实现WebSocket服务器应用

在vs2019里创建,记得先包含QT模块:websockets,

右键单击项目->属性->Qt Project Settings->QT Moduls->选择websockets

1、主要功能实现

(1)通过Qt的QWebSocketServer类实现WebSocket服务器,用于处理客户端的连接和消息通信。

(2)可以开启、关闭服务器,监听指定的IP地址和端口,处理新的客户端连接,以及处理客户端断开连接事件。

(3)可以接收客户端发送的消息,并实现消息的转发功能。

2、整体思路:

2.1开启服务器

用户通过界面输入IP地址和端口号来开启WebSocket服务器。

WebsocketServerDemo::WebsocketServerDemo(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);
   
    this->setWindowTitle(u8"Websocket Server");
    this->resize(1000, 600);

    ui.lineEdit_IP->setText("192.168.0.109"); //IP地址输入框
    ui.lineEdit_Port->setText("8000");//端口号输入框

    //创建websocketServer,用于处理WebSocket连接。
    m_WebSocketServer = new QWebSocketServer(u8"server", QWebSocketServer::NonSecureMode);
}
2.2保存客户端信息

当有新的客户端连接时,将其添加到m_clients列表中,并保存对应的URL和套接字到mapSocket映射中,方便后续管理。 

//处理新的链接,保存连接并更新在线用户列表。
void WebsocketServerDemo::onNewConnection()
{
    //使用nextPendingConnection方法获取下一个挂起的连接
    //返回一个QWebSocket指针pSocket,表示新连接的套接字
    pSocket = m_WebSocketServer->nextPendingConnection();
    //将新连接pSocket添加到m_clients列表中,用于跟踪所有客户端连接。
    m_clients << pSocket;

    //每个client上线时,链接他的textMessageReceived信号,处理接受的消息
    connect(pSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(processTextMessage(QString)));
    //用户掉线处理
    connect(pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));

    //如何知道是哪个client发送的消息
    //获取客户端连接的URL,用于标识客户端。
    QString peerName = pSocket->requestUrl().toString();
    cout << "peerName = " << peerName.toStdString() << endl;

    //将客户端连接的URL和pSocket套接字保存到mapSocket映射中,用于后续管理和查找客户端连接。
    mapSocket[peerName] = pSocket;

    //将客户端连接的URL添加到在线用户列表listWidget_OnlineUser中,显示在线用户。
    ui.listWidget_OnlineUser->addItem(peerName);
}
2.3连接槽函数

每个客户端连接都会关联处理消息接收和断开连接的槽函数。

    //每个client上线时,链接他的textMessageReceived信号,处理接受的消息
    connect(pSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(processTextMessage(QString)));
    //用户掉线处理
    connect(pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
2.4显示消息信息

在处理消息时,会显示时间、客户端信息和消息内容,并实现消息转发的功能。 

//处理接收到的消息,显示在文本框中并处理消息转发。
void WebsocketServerDemo::processTextMessage(QString message) 
{
    QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
    QString item = pSocket->requestUrl().toString();
    ui.textEdit_RecvMsg->append(time + "" + item + "\n" + message);

    //处理消息转发
    //...

}
2.5客户端断开连接时的处理

当客户端断开连接时,会从列表、映射中移除对应关系,并更新界面显示。 

//客户端连接断开的操作,从在线用户列表中移除断开的客户端。
//处理客户端断开连接时的清理工作,包括从列表中移除客户端连接、从映射中移除对应关系,并更新界面显示。
void WebsocketServerDemo::socketDisconnected() 
{
    //智能索引遍历存储客户端连接的m_clients列表中的每个QWebSocket套接字sk
    for (auto sk : m_clients)
    {
        if (!sk->isValid())//检查当前套接字sk是否有效,即客户端是否已断开连接
        {
            QString temp_key; //用于暂时存储要删除的客户端连接的URL。
            ui.textEdit_RecvMsg->append("map size = " + QString(mapSocket.size()) + "\n");//显示当前mapSocket映射的大小。
           
            //遍历mapSocket映射,查找与当前客户端套接字sk对应的URL
            for (auto it = mapSocket.begin(); it!=mapSocket.end(); it++)
            {
                if (it.value() == sk)
                {
                    //删除该客户端连接的相关信息:

                    //通过URL在在线用户列表中找到对应项,并删除。
                    QList<QListWidgetItem*> list;
                    list = ui.listWidget_OnlineUser-> findItems(it.key(), Qt::MatchCaseSensitive);

                    //从映射中移除该URL对应的套接字。
                    QListWidgetItem* sel = list[0];
                    int r = ui.listWidget_OnlineUser->row(sel);

                    QListWidgetItem* item = ui.listWidget_OnlineUser->takeItem(r);
                    ui.listWidget_OnlineUser->removeItemWidget(item);

                    delete item;
                    //从m_clients列表中移除当前客户端套接字sk。
                    m_clients.removeOne(sk);

                    QString time = current_date_time->currentDateTime().toString("yyyy.MM.dd hh:mm:ss.zzz ddd");
                    ui.textEdit_RecvMsg->append(time + "" + it.key() + "下线了\n");

                    ///将当前URL存储在temp_key中,用于后续删除操作。
                    temp_key = it.key();
                }
            }

            //从mapSocket映射中移除存储在temp_key中的URL并显示移除后的mapSocket大小
            mapSocket.remove(temp_key);
            ui.textEdit_RecvMsg->append("after remove, map size = " + QString(mapSocket.size()) + "\n");
        }
    }
}

3、类结构分析

 WebsocketServerDemo类是主要的应用类,继承自QWidget,负责处理界面相关的操作和WebSocket服务器的管理。

在构造函数中初始化界面和WebSocket服务器对象。

在析构函数中关闭WebSocket服务器。

包含槽函数:

on_btnOpenServer_clicked()用于开启服务器,
on_btnCloseServer_clicked()用于关闭服务器,
onNewConnection()处理新的连接,
processTextMessage()处理接收到的消息,
socketDisconnected()处理客户端断开连接,
on_btnSend_clicked()用于向所有客户端发送消息。


以上就是Qt里实现websocket server服务器端的简单介绍。

都看到这里了,点个赞再走呗朋友~

加油吧,预祝大家变得更强!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/568590.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

万界星空科技电机行业MES+商业电机行业开源MES+项目合作

要得出mes系统解决方案在机电行业的应用范围&#xff0c;我们先来看一下传统机电行业的管理难题&#xff1a; 1、 产品标准化程度较低&#xff0c;制造工艺复杂&#xff0c;生产周期较长&#xff0c;产品质量不稳定&#xff1b; 2、 自动化程度低&#xff0c;大多数工序以手工…

【视频异常检测】Open-Vocabulary Video Anomaly Detection 论文阅读

Open-Vocabulary Video Anomaly Detection 论文阅读 AbstractMethod3.1. Overall Framework3.2. Temporal Adapter Module3.3. Semantic Knowledge Injection Module3.4. Novel Anomaly Synthesis Module3.5. Objective Functions3.5.1 Training stage without pseudo anomaly …

电子信息制造工厂5G智能制造数字孪生可视化平台,推进数字化转型

电子信息制造工厂5G智能制造数字孪生可视化平台&#xff0c;推进数字化转型。5G智能制造数字孪生可视化平台利用5G网络的高速、低延迟特性&#xff0c;结合数字孪生技术和可视化界面&#xff0c;为电子信息制造工厂提供了一种全新的生产管理模式。不仅提升生产效率&#xff0c;…

设计模式(三):抽象工厂模式

设计模式&#xff08;三&#xff09;&#xff1a;抽象工厂模式 1. 抽象工厂模式的介绍2. 抽象工厂模式的类图3. 抽象工厂模式的实现3.1 创建摩托车的接口3.2 创建摩托车的具体实现3.3 创建汽车的接口3.4 创建汽车的具体产品3.5 创建抽象工厂3.6 创建具体工厂3.7 创建工厂生成器…

Fisher判别示例:鸢尾花(iris)数据(R)

先读取iris数据&#xff0c;再用程序包MASS&#xff08;记得要在使用MASS前下载好该程序包&#xff09;中的线性函数lda()作判别分析&#xff1a; data(iris) #读入数据 iris #展示数据 attach(iris) #用变量名绑定对应数据 library(MASS) #加载MASS程序包 ldlda(Species~…

《ElementPlus 与 ElementUI 差异集合》el-select 显示下拉列表在 Cesium 场景中无法监听关闭

前言 仅在 Element UI 时有此问题&#xff0c;Element Plus 由于内部结构差异较大&#xff0c;不存在此问题。详见《el-select 差异点&#xff0c;如&#xff1a;高、宽、body插入等》&#xff1b; 问题 点击空白处&#xff0c;下拉列表可监听并关闭&#xff1b;但在 Cesium…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之五 简单进行车牌检测和识别 一、简单介绍 二、简单进行车牌检测和识别实现原理 …

鸿蒙(HarmonyOS)性能优化实战-Swiper高性能开发

背景 在应用开发中&#xff0c;Swiper 组件常用于翻页场景&#xff0c;比如&#xff1a;桌面、图库等应用。Swiper 组件滑动切换页面时&#xff0c;基于按需加载原则通常会在下一个页面将要显示时才对该页面进行加载和布局绘制&#xff0c;这个过程包括&#xff1a; 如果该页面…

解决VSCode中“#include错误,请更新includePath“问题

目录 1、问题原因 2、解决办法 1、问题原因 在编写C程序时&#xff0c;想引用头文件但是出现如下提示&#xff1a; &#xff08;1&#xff09;首先检查要引用的头文件是否存在&#xff0c;位于哪里。 &#xff08;2&#xff09;如果头文件存在&#xff0c;在编译时提醒VSCo…

【iOS】类与对象底层探索

文章目录 前言一、编译源码二、探索对象本质三、objc_setProperty 源码探索四、类 & 类结构分析isa指针是什么类的分析元类元类的说明 五、著名的isa走位 & 继承关系图六、objc_class & objc_objectobjc_class结构superClassbitsclass_rw_tclass_ro_tro与rw的区别c…

关于Modbus TCP 编码及解码方式分析

一.Modbus TCP 基本概念 1.基本概念 ①Coil和Register   Modbus中定义的两种数据类型。Coil是位&#xff08;bit&#xff09;变量&#xff1b;Register是整型&#xff08;Word&#xff0c;即16-bit&#xff09;变量。 ②Slave和Master与Server和Client   同一种设备在不同…

BUUCTF——[RoarCTF 2019]Easy Java

BUUCTF——[RoarCTF 2019]Easy Java 1.既然是登录框嘛&#xff0c;不得随便输入个弱口令&#xff0c;进行尝试 2.使用弱口令爆破了一下&#xff0c;直接就是429,无果 3.查看版本信息 4.帮助文档这里测试啦任意文件读取&#xff0c;无果 5.知道服务器的名称是openresty 6.…

jvm知识点总结(一)

JVM的跨平台 java程序一次编写到处运行。java文件编译生成字节码&#xff0c;jvm将字节码翻译成不同平台的机器码。 JVM的语言无关性 JVM只是识别字节码&#xff0c;和语言是解耦的&#xff0c;很多语言只要编译成字节码&#xff0c;符合规范&#xff0c;就能在JVM里运行&am…

信息系统项目管理师0066:过程管理(5信息系统工程—5.1软件工程—5.1.6过程管理)

点击查看专栏目录 文章目录 5.1.6过程管理1.成熟度模型2.成熟度等级5.1.6过程管理 软件过程能力是组织基于软件过程、技术、资源和人员能力达成业务目标的综合能力。包括治理能力、开发与交付能力、管理与支持能力、组织管理能力等方面。软件过程能力成熟度是指组织在提升软件产…

[Qt的学习日常]--初识Qt

前言 作者&#xff1a;小蜗牛向前冲 名言&#xff1a;我可以接受失败&#xff0c;但我不能接受放弃 如果觉的博主的文章还不错的话&#xff0c;还请点赞&#xff0c;收藏&#xff0c;关注&#x1f440;支持博主。如果发现有问题的地方欢迎❀大家在评论区指正 目录 一、Qt的基本…

docker容器技术篇:容器集群管理实战mesos+zookeeper+marathon(一)

容器集群管理实战mesoszookeepermarathon&#xff08;一&#xff09; mesos概述 1.1 Mesos是什么 Apache Mesos 是一个基于多资源调度的集群管理软件&#xff0c;提供了有效的、跨分布式应用或框架的资源隔离和共享&#xff0c;可以运行 Hadoop、Spark以及docker等。 1.2 为…

C++中的list类模拟实现

目录 list类模拟实现 list类节点结构设计 list类非const迭代器结构设计 迭代器基本结构设计 迭代器构造函数 operator()函数 operator*()函数 operator!()函数 operator(int)函数 operator--()函数 operator--(int)函数 operator()函数 operator->()函数 list…

鸿蒙OpenHarmony【LED外设控制】 (基于Hi3861开发板)

概述 OpenHarmony WLAN模组基于Hi3861平台提供了丰富的外设操作能力&#xff0c;包含I2C、I2S、ADC、UART、SPI、SDIO、GPIO、PWM、FLASH等。本文介绍如何通过调用OpenHarmony的NDK接口&#xff0c;实现对GPIO控制&#xff0c;达到LED闪烁的效果。其他的IOT外设控制&#xff0…

C++ | Leetcode C++题解之第45题跳跃游戏II

题目&#xff1a; 题解&#xff1a; class Solution { public:int jump(vector<int>& nums) {int maxPos 0, n nums.size(), end 0, step 0;for (int i 0; i < n - 1; i) {if (maxPos > i) {maxPos max(maxPos, i nums[i]);if (i end) {end maxPos;s…

Opencv_10_自带颜色表操作

void color_style(Mat& image); Opencv_10_自带颜色表操作&#xff1a; void ColorInvert::color_style(Mat& image) { int colormap[] { COLORMAP_AUTUMN, COLORMAP_BONE , COLORMAP_JET , COLORMAP_WINTER, COLORMAP_RAINBOW , COLOR…
最新文章