【C++】Qt:WebSocket客户端示例

😏★,°:.☆( ̄▽ ̄)/$:.°★ 😏
这篇文章主要介绍WebSocket客户端示例。
学其所用,用其所学。——梁启超
欢迎来到我的博客,一起学习,共同进步。
喜欢的朋友可以关注一下,下次更新不迷路🥞

文章目录

    • :smirk:1. WebSocket客户端介绍
    • :blush:2. 环境安装与配置
    • :satisfied:3. 基于Qt的WebSocket客户端示例

😏1. WebSocket客户端介绍

WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,允许在客户端和服务器之间实时交换数据。WebSocket 客户端是指使用 WebSocket 协议与服务器端建立连接并进行数据交换的程序或组件。

实现 WebSocket 客户端的步骤:

  1. 建立连接: WebSocket 客户端首先需要与服务器建立连接,通常通过 WebSocket URL(ws:// 或 wss://)来连接到服务器。

  2. 发送和接收数据: 一旦连接建立成功,客户端可以通过发送消息给服务器来交换数据,并从服务器接收响应消息。

  3. 处理事件: WebSocket 客户端可以监听连接状态、错误和消息等事件,并根据需要处理这些事件。

  4. 关闭连接: 在通信结束后,客户端应该关闭 WebSocket 连接,释放资源。

😊2. 环境安装与配置

Windows + Qt5

效果如下:

在这里插入图片描述

😆3. 基于Qt的WebSocket客户端示例

// qt.pro
QT       += websockets
// websocketclient.h
#ifndef WEBSOCKETCLIENT_H
#define WEBSOCKETCLIENT_H

#include <QObject>
#include <QtWebSockets>
#include <QDebug>
#include <QUrl>

class WebSocketClient : public QObject
{
    Q_OBJECT
public:
    explicit WebSocketClient(QObject *parent = nullptr);
    ~WebSocketClient();

    void connectUrl(QString url); // 连接websocket服务器的URL
    void close(); // 关闭websocket
    void sendTextMsg(const QString &message); // 发送Text类型的消息
    void sendBinaryMsg(const QByteArray &data); // 发送Binary类型的消息
    bool getConStatus(); // 返回服务器连接状态

signals:
    void sigRecvTextMsg(QString message); // 接受到Text类型消息的信号

private slots:
    void slotConnected(); // 连接成功
    void slotDisconnected(); // 断开连接
    void slotRecvTextMsg(QString message); // 接受字符数据
    void slotRecvBinaryMsg(QByteArray message); // 接受二进制数据
    void slotError(QAbstractSocket::SocketError error); // 响应报错

private:
    void reconnect(); // 断开重连

    QWebSocket  *m_pWebSocket;
    QUrl m_url;
    bool m_bConnected = false; // 为true,表明已连接服务器,否则未连接上
};

#endif // WEBSOCKETCLIENT_H

// websocketclient.cpp
#include "websocketclient.h"

WebSocketClient::WebSocketClient(QObject *parent) : QObject(parent)
{
    m_pWebSocket = new QWebSocket();

     // 连接相应的信号槽
    connect(m_pWebSocket, SIGNAL(connected()), this, SLOT(slotConnected()));
    connect(m_pWebSocket, SIGNAL(disconnected()), this, SLOT(slotDisconnected()));
    connect(m_pWebSocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotError(QAbstractSocket::SocketError)));
}

WebSocketClient::~WebSocketClient()
{
    if(m_pWebSocket != 0)
    {
        m_pWebSocket->deleteLater();
        m_pWebSocket = 0;
    }
}

// 连接websocket服务器的URL
void WebSocketClient::connectUrl(QString url)
{
    m_url = QUrl(url);
    m_pWebSocket->open(m_url);
}

// 关闭websocket
void WebSocketClient::close()
{
    m_pWebSocket->close();
}

// 发送Text类型的消息
void WebSocketClient::sendTextMsg(const QString &message)
{
    if(!m_bConnected)
    {
        qDebug() << __FILE__ << __LINE__ << "Failed to" << __FUNCTION__ << ", it's not running...";
        return;
    }
    //qDebug() << "send: " << message;
    m_pWebSocket->sendTextMessage(message);
}

// 发送Binary类型的消息
void WebSocketClient::sendBinaryMsg(const QByteArray &data)
{
    if(!m_bConnected)
    {
        qDebug() << __FILE__ << __LINE__ << "Failed to" << __FUNCTION__ << ", it's not running...";
        return;
    }
    m_pWebSocket->sendBinaryMessage(data);
}

// 返回服务器连接状态
bool WebSocketClient::getConStatus()
{
    return m_bConnected;
}

// 连接成功
void WebSocketClient::slotConnected()
{
    qDebug()<<"connect successful";
    m_bConnected = true;

    connect(m_pWebSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(slotRecvTextMsg(QString)));
    connect(m_pWebSocket, SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(slotRecvBinaryMsg(QByteArray)));
}

// 断开连接
void WebSocketClient::slotDisconnected()
{
    qDebug() << __FILE__ << __LINE__ << "disconnected";
    reconnect();
}

// 接受字符数据
void WebSocketClient::slotRecvTextMsg(QString message)
{
    emit sigRecvTextMsg(message);
}

// 接受二进制数据
void WebSocketClient::slotRecvBinaryMsg(QByteArray message)
{
    qDebug() << "slotRecvBinaryMsg: " << message;
}

// 响应报错
void WebSocketClient::slotError(QAbstractSocket::SocketError error)
{
    qDebug() << __FILE__ << __LINE__ << (int)error << m_pWebSocket->errorString();
}

// 断开重连
void WebSocketClient::reconnect()
{
   qDebug() << "websocket reconnected";
   m_pWebSocket->abort();
   m_pWebSocket->open(m_url);
}

// widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QListWidget>
#include <QLineEdit>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QMessageBox>
#include "websocketclient.h"

//namespace Ui {
//class Widget;
//}

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void slotSendMsg(); // 发送消息的槽函数
    void slotRecvTextMsg(QString sMessage); // 接受WebSocketClient传来的文本消息

private:
//    Ui::Widget *ui;

    QListWidget *listwidget;
    QLineEdit *lineedit;

    WebSocketClient *m_pWebSocketClinet; // WebSocket客户端

};

#endif // WIDGET_H

// widget.cpp
#include "widget.h"
//#include "ui_widget.h"

Widget::Widget(QWidget *parent) :
    QWidget(parent)
//    ui(new Ui::Widget)
{
//    ui->setupUi(this);
    this->setWindowTitle("WebSocket客户端");

    // 初始化窗口部件
    listwidget = new QListWidget;
    lineedit = new QLineEdit;
    QPushButton *sendbutton = new QPushButton("发  送");
    QPushButton *cancelbutton = new QPushButton("取  消");
    this->connect(sendbutton, SIGNAL(clicked()), this, SLOT(slotSendMsg()));
    this->connect(cancelbutton, SIGNAL(clicked()), this,SLOT(close()));

    // 布局
    QHBoxLayout * hlayout = new QHBoxLayout;
    hlayout->addStretch(0);
    hlayout->addWidget(sendbutton);
    hlayout->addWidget(cancelbutton);
    QVBoxLayout *vlayout = new QVBoxLayout(this);
    vlayout->addWidget(listwidget);
    vlayout->addWidget(lineedit);
    vlayout->addLayout(hlayout);

    // 初始化服务器
    m_pWebSocketClinet = new WebSocketClient;
    m_pWebSocketClinet->connectUrl("ws://localhost:8080");
    connect(m_pWebSocketClinet, SIGNAL(sigRecvTextMsg(QString)), this, SLOT(slotRecvTextMsg(QString)));
}

Widget::~Widget()
{
//    delete ui;
}

// 发送消息的槽函数
void Widget::slotSendMsg()
{
    QString content = lineedit->text(); //获取单行文本框内要发送的内容
    if(!content.isEmpty())
    {
        QDateTime datetime = QDateTime::currentDateTime();
        QString str = "send to server : " + datetime.toString("yyyy-M-dd hh:mm:ss") + tr("\n");
        str += content;
        listwidget->addItem(str);   // 将要发送的内容显示在listwidget
        m_pWebSocketClinet->sendTextMsg(str); // 发送消息到服务器
    }
    else
    {
        QMessageBox::critical(this, "错误", "不能发送空消息!", QMessageBox::Ok);
    }
    lineedit->clear();
}

// 接受WebSocketClient传来的文本消息
void Widget::slotRecvTextMsg(QString sMessage)
{
    // 加上时间帧
    QDateTime datetime = QDateTime::currentDateTime();
    QString str = tr("recv from server : ") + datetime.toString("yyyy-M-dd hh:mm:ss") + tr("\n");
    str += sMessage;

    listwidget->addItem(str);   // 将接收到的内容加入到listwidget
}

请添加图片描述

以上。

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

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

相关文章

k8s-kubectl命令详解、Pod创建过程、Pod的生命周期、定制Pod、资源对象文件

集群管理 一、如何管理集群 kubectl是用于管理Kubernetes集群的命令行工具 二、语法格式&#xff1a; kubectl [command] [TYPE] [NAME] [flags] command&#xff1a;子命令&#xff0c;如create&#xff0c;get&#xff0c;describe&#xff0c;delete type&#xff1a;…

redis集群数据一致性如何保证?

一般的做法是对key进行hash&#xff0c;比如有4台机器&#xff0c;就对4取模。 这样的坏处是增加或者减少机器的时候&#xff0c;会有大量数据进行迁移。 业界做法是用一致性哈希算法&#xff0c;将机器节点的ip值&#xff0c;对一个很大的数取模比如2^32&#xff0c; 用一个…

Prometheus 配置Basic auth认证

官方配置说明&#xff1a; Basic auth | Prometheus 一、生成密码加密串 Prometheus于2.24版本&#xff08;包括2.24&#xff09;之后提供Basic Auth功能进行加密访问&#xff0c;在浏览器登录UI的时候需要输入用户密码&#xff0c;访问Prometheus api的时候也需要加上用户密…

优质的短效HTTP代理具备什么优点?

随着网络时代的蓬勃发展&#xff0c;数据的获取与处理成为了企业决策和市场竞争的关键。在这场数据的角逐中&#xff0c;优质的短效HTTP代理脱颖而出&#xff0c;备受业界瞩目。优质的短效HTTP代理&#xff0c;提供了稳定的网络连接和匿名性&#xff0c;更为数据采集提供了关键…

Echarts组件初步封装

一、业务场景&#xff1a; 最近在vue中使用echarts时 有多处需要用到各种图表&#xff0c;想着自己封装一个便于多次复用 为了避免大家走弯路&#xff0c;为大家整理了一下&#xff0c;粘走可以直接用的那种 二、具体实现步骤&#xff1a; 1、先在终端安装echarts npm install…

管理类联考–复试–英文面试–问题--规划介绍原因做法--纯英文版

借鉴 https://www.bilibili.com/video/BV1Dk4y187zN/?p4&spm_id_from333.880.my_history.page.clickhttps://www.bilibili.com/video/BV1Dk4y187zN/?p4&spm_id_from333.880.my_history.page.click https://ttsreader.com/zh/https://ttsreader.com/zh/ 规划 视频版…

一文掌握Java动态代理的奥秘与应用场景

一、基本概念 为某个对象提供一个代理&#xff0c;以控制对这个对象的访问。代理类和委托类有共同的父类或父接口&#xff0c;这样在任何使用委托类对象的地方都可以用代理对象来替代。代理类负责请求的预处理、过滤、将请求分派委托类处理、以及委托类执行完请求后的后续处理。…

中国软件评测中心发布《健康软件安全白皮书》,美创参编分享方案实践

日前&#xff0c;中国软件评测中心网络安全和数据安全研究测评事业部发布《健康软件安全白皮书》研究成果&#xff0c;美创科技深度参与此次白皮书编写工作&#xff0c;针对健康软件目前面临的安全风险&#xff0c;分享数据安全建设思路。 白皮书详细剖析健康软件面临的网络和数…

盲盒抽卡机小程序:探索神秘盲盒,尽享抽卡乐趣

在盲盒文化的热潮中&#xff0c;盲盒抽卡机作为一种深受大众喜爱的娱乐形式&#xff0c;正逐渐成为市场上的新宠。为了满足广大盲盒爱好者和抽卡玩家的需求&#xff0c;我们积极投身于盲盒抽卡机小程序的开发&#xff0c;旨在通过创新的技术手段&#xff0c;为用户带来全新的盲…

PyTorch出现:RuntimeError: An attempt has been made to start a new process...报错

1.查看显卡&#xff1a; 第一步&#xff1a;同时按下键盘的winr键&#xff0c;输入cmd 第二步&#xff1a;随后输入 nvidia-smi 2.查看下载安装的包&#xff1a; conda list conda list 3.问题报错 PyTorch出现&#xff1a;RuntimeError: An attempt has been made to …

解决vue3中刷新浏览器页面的axios请求状态变为canceled

最近在开发中要加一个悲观锁的功能&#xff0c;具体需求是&#xff1a;用户1和用户2不能同时打开一个模型进行编辑&#xff0c;用户1优先进入模型后&#xff0c;要对该模型进行上锁&#xff0c;关闭该模型或刷新页面时要进行解锁&#xff0c;此时在刷新页面时出现了问题。 刷新…

线上linux服务器升级nginx

一个nginx版本空包 一个pcre文件 一个zlib文件 ./configure配置文件 make编译 make install复制所有文件到nginx 如果nginx -v无版本号 检查环境变量cat /etc/profile 编辑 环境变量vi /etc/profile 按i进入编辑模式 按esc进入查看模式 因为path中并未使用%JAVA_HOME%字样…

力扣---全排列---回溯

思路&#xff1a; 递归做法&#xff0c;一般会有visit数组来判断第 i 位是否被考虑了。我们先考虑第0位&#xff0c;再考虑第1位&#xff0c;再考虑第2位...dfs函数中还是老套路&#xff0c;先判定特殊条件&#xff0c;再从当下的角度&#xff08;决定第 j 位是哪个元素&#x…

Docker 应用部署

MySQL部署 需求 在 Docker 容器中部署 MySQL &#xff0c;并通过外部 mysql 客户端操作 MySQL Server 。 步骤 1. 搜索mysql镜像 docker search mysql 2. 拉取mysql镜像 docker pull mysql:5.6 3. 创建容器&#xff0c;设置端口映射、目录映射 事先在/root目录下创建m…

VScode手动安装vsix格式插件,提示安装插件与code版本不兼容问题

问题描述: vscode手动按装插件提示"插件不兼容code版本 原因方案:修改安装包内的package.json文件中的版本号与vscode版本号对应即可 解决步骤 以(adpyke.codesnap-1.3.4.vsix)安装包为例 手动安装vscode弹出 无法安装扩展“adpyke.codesnap-1.3.4”&#xff0c;它与 …

每周一算法:迭代加深A*

题目链接 AcWing 180. 排书 题目描述 给定 n n n 本书&#xff0c;编号为 1 ∼ n 1\sim n 1∼n。 在初始状态下&#xff0c;书是任意排列的。 在每一次操作中&#xff0c;可以抽取其中连续的一段&#xff0c;再把这段插入到其他某个位置。 我们的目标状态是把书按照 1 ∼…

提高企业员工生产力的办法

在现代商业环境中&#xff0c;提高企业员工生产力是企业持续发展的关键因素之一。员工生产力的提升不仅有助于企业提高运营效率&#xff0c;还能增强企业的市场竞争力。那么&#xff0c;如何有效地提高企业员工生产力呢&#xff1f;本文将就此问题进行探讨。 一、引入先进技术软…

[ C++ ] STL---stack与queue

目录 stack简介 stack的常用接口 queue简介 queue的常用接口 stack的模拟实现 queue的模拟实现 stack简介 1. stack是具有后进先出操作的一种容器适配器&#xff0c;其只能从容器的一端进行元素的插入与删除操作&#xff1b; 2. stack是作为容器适配器被实现的&#xff0…

jmeter接口自动化测试框架

接口测试可以分为两部分&#xff1a; 一是线上接口&#xff08;生产环境&#xff09;自动化测试&#xff0c;需要自动定时执行&#xff0c;每5分钟自动执行一次&#xff0c;相当于每5分钟就检查一遍线上的接口是否正常&#xff0c;有异常能够及时发现&#xff0c;不至于影响用…

基于preCICE的Fluent适配器开发分享

1 开发目的 后向台阶流是流动分离现象的经典代表&#xff0c;为了更有效地控制后向台阶流中的重要特征参数&#xff0c;如背部分离压强和湍流强度&#xff0c;进行了耦合分析。通过该耦合分析&#xff0c;能够深入研究后向台阶流的特性&#xff0c;并探索如何控制这些参数对流…