基于websocket的简单通信

首次接触websocket通信协议,不足之处希望指出一起进步。

简述

websocket是基于tcp协议的一种网络通信协议,分为客户端和服务端,可以实现客户端与服务端的双向通信。
与tcp的不同之处是:
1.客户端与服务端只需要一次握手协议,就可以建立比较持久的网络连接;
2.客户端不需要向服务端发送连接请求。
服务端监听指定的端口之后,客户端只需打开服务端的url,就可建立连接。

简单的项目实例

  1. 项目简述
    在客户端与服务端建立连接的情况下,服务端向客户端发送json字符串,客户端接收到json字符串并显示,客户端一旦收到二进制消息,服务端接收来自客户端的文本消息,并向客户端发送文本消息。

  2. 项目运行效果图
    服务端运行效果:在这里插入图片描述
    客户端运行效果:
    在这里插入图片描述

  3. 项目源码
    客户端
    main.cpp

#include "dialog.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Dialog w;w.createWebsocket();w.show();return a.exec();
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QtWebSockets/QWebSocket>QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACEclass Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();void createWebsocket();public slots:void slot_onConnected();void slot_onDisconnected();void slot_onTextMsgRecevied(const QString &msg);void slot_onBinaryMessageReceived(const QByteArray &message);void slot_onError(QAbstractSocket::SocketError error);private:Ui::Dialog *ui;QWebSocket *m_client;
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{ui->setupUi(this);setWindowTitle(tr("Client"));
}Dialog::~Dialog()
{delete ui;
}void Dialog::createWebsocket()
{m_client = new QWebSocket();m_client->open(QUrl("ws://localhost:6666"));connect(m_client, &QWebSocket::connected, this, &Dialog::slot_onConnected);connect(m_client, &QWebSocket::disconnected, this, &Dialog::slot_onDisconnected);connect(m_client, &QWebSocket::binaryMessageReceived,this, &Dialog::slot_onBinaryMessageReceived);connect(m_client, &QWebSocket::textMessageReceived,this, &Dialog::slot_onTextMsgRecevied);connect(m_client,SIGNAL(error(QAbstractSocket::SocketError)),this,SLOT(slot_onError(QAbstractSocket::SocketError)));
}void Dialog::slot_onConnected()
{
//    connect(m_client, &QWebSocket::binaryMessageReceived,this, Dialog::slot_onTextMsgRecevied);
//    connect(m_client, &QWebSocket::textMessageReceived,this, Dialog::slot_onTextMsgRecevied);m_client->sendTextMessage(QStringLiteral("Hello,server!我连接你成功了"));
}void Dialog::slot_onDisconnected()
{m_client->close();if(m_client != NULL){delete m_client;m_client = NULL;}
}void Dialog::slot_onTextMsgRecevied(const QString &msg)
{ui->plainTextEdit->appendPlainText(msg);
}void Dialog::slot_onBinaryMessageReceived(const QByteArray &message)
{std::string strMsg = message.toStdString();//接收JSON字符串ui->plainTextEdit->appendPlainText(QString::fromStdString(strMsg));
}void Dialog::slot_onError(QAbstractSocket::SocketError error)
{QTextStream(stdout)<<m_client->errorString();
}

ui文件
在这里插入图片描述
客户端项目结构
在这里插入图片描述
服务端
main.cpp

#include "dialog.h"#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Dialog w;w.createWebServer();w.show();return a.exec();
}

dialog.h

#ifndef DIALOG_H
#define DIALOG_H#include <QDialog>
#include <QtWebSockets/QWebSocketServer>
#include <QtWebSockets/QWebSocket>QT_BEGIN_NAMESPACE
namespace Ui { class Dialog; }
QT_END_NAMESPACEclass Dialog : public QDialog
{Q_OBJECTpublic:Dialog(QWidget *parent = nullptr);~Dialog();void createWebServer();QString getCurrFilePath(QString fileName);QByteArray readJsonConfigFile(QString &fileName);public slots:void slot_onNewConnection();void slot_processMessage(const QString &msg);void slot_socketDisconnected();void slot_binaryMessageReceived(const QByteArray &message);
private:Ui::Dialog *ui;QWebSocketServer *m_serve;QWebSocket *      m_client;
};
#endif // DIALOG_H

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include <QDebug>
#include <QFile>Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{ui->setupUi(this);setWindowTitle(tr("Server"));
}Dialog::~Dialog()
{if(m_serve != NULL){m_serve->close();//设置了父窗口,就不用delete}delete ui;
}void Dialog::createWebServer()
{m_serve = new QWebSocketServer("test1",QWebSocketServer::NonSecureMode,this);//非安全swm_serve->listen(QHostAddress::LocalHost,6666);connect(m_serve, &QWebSocketServer::newConnection, this, &Dialog::slot_onNewConnection);
}void Dialog::slot_onNewConnection()
{m_client = m_serve->nextPendingConnection();QString strFileName = getCurrFilePath("config2.json");QByteArray jsonArray = readJsonConfigFile(strFileName);m_client->sendBinaryMessage(jsonArray);
//    m_client->sendTextMessage("什么??客户端你好!");connect(m_client,&QWebSocket::binaryMessageReceived,this,&Dialog::slot_binaryMessageReceived);connect(m_client, &QWebSocket::textMessageReceived,this, &Dialog::slot_processMessage);connect(m_client, &QWebSocket::disconnected,this, &Dialog::slot_socketDisconnected);
}void Dialog::slot_processMessage(const QString &msg)
{//   m_client->sendTextMessage("客户端,你收到消息了?");ui->textEdit->append(msg);m_client->sendTextMessage("客户端,我收到你的消息了");
}void Dialog::slot_socketDisconnected()
{m_client->close();
}void Dialog::slot_binaryMessageReceived(const QByteArray &message)
{ui->textEdit->append(QString::fromLocal8Bit(message));
}QString Dialog::getCurrFilePath(QString fileName)
{QString strFileName =  QCoreApplication::applicationDirPath();//获取可执行文件的路径strFileName += "/" + fileName;return strFileName;
}QByteArray Dialog::readJsonConfigFile(QString &fileName)
{QByteArray allData;qDebug()<<"文件路径及名称:"<<fileName;QFile file(fileName);if (!file.open(QIODevice::ReadOnly)){qDebug()<<"json配置文件读取失败!";return allData;}allData = file.readAll();file.close();qDebug()<<"json文件内容:"<<allData;return allData;
}

ui文件
在这里插入图片描述
服务端项目结构
在这里插入图片描述
5. 总结
websocket在通信的过程中服务端的步骤:
(1)创建QWebSocketServer对象或着指向QWebSocketServer的指针,创建时需指明服务器的名称,sslmode(即安全模式还是非安全模式,一般非SSL的情况下,采用的时非安全模式),另外还可以指明父窗口;
(2)监听IP和端口;
(3)绑定信号与槽函数,涉及到的常用信号与槽的绑定有:
@1 newConnection(),与客户端建立新的连接后触发这个信号;
@2 serverError(QWebSocketProtocol::CloseCode closeCode),服务器发生错误时触发该信号;
@3 可以在客户端建立连接后,服务端绑定客户端收到消息后的信号;
@4 可以在客户端建立连接后,服务端绑定客户端断开连接的信号;
(4)关闭服务端连接。
websocket在通信的过程中客户端的步骤:
(1)创建QWebSocket对象或着指向QWebSocket的指针;
(2)打开服务端的url;
(3)绑定信号与槽函数,常用的信号与槽函数的绑定如下:
@1 connected(),与服务端连接建立之后,信号被触发;
@2 disconnected(),与服务端连接断开之后,信号被触发;
@3 textMessageReceived(const QString &message),有文本消息到来的时候,信号被触发;
@4 binaryMessageReceived(const QByteArray &message),有二进制消息到来的时候,信号被触发;
@5 error(QAbstractSocket::SocketError error),发生错误的时候信号被触发;
6. 注意事项
(1).pro文件中添加QT += websockets,需加头文件#include <QtWebSockets/QWebSocket>和#include <QtWebSockets/QWebSocketServer>。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

OpenGL ES 名词解释(一)

目录 一.前言二.OpenGL ES 上下文三.OpenGL ES 状态机四.缓存五.渲染六.纹理七.光栅化 Rasterization八.片元着色器九.顶点着色器十.着⾊语言 GLSL十一.着色器使用流程十二.着色器的渲染流程十三.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenG…

大龄程序员失业后,看他们是如何破局突围的? | 技术头条

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;作者&#xff1a;逆流的鱼yuiop转自&#xff1a;何俊林王小波在《黄金时代》里写道&am…

分布式架构系列: 负载均衡技术详解 | 技术头条

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;作者&#xff1a;ITFLY8转自&#xff1a;架构师技术联盟面对大量用户访问、高并发请求…

第七篇:Spring Boot整合Thymeleaf_入门试炼03

基本语法实战案例01 在ThymeleafController中添加此方法 RequestMapping("/show5")public String showInfo5(Model model) {model.addAttribute("msg", "Thymeleaf 第一个案例");model.addAttribute("key", new Date());return &quo…

Qt下自适应分辨率

qt下自适应分辨率应该有两种方法&#xff1a;通过栅格布局&#xff1b;通过缩放比。 本人采用的是缩放比来适应不同的分辨率。首先定义一个类实现屏幕分辨率和长宽缩放比的获取&#xff0c;由于该类可能被多个ui界面使用&#xff0c;所以定义为一个单例模式。代码如下&#xff…

OpenGL ES EGL 简介

目录 一.EGL 简介二.EGL 跨平台之 ANGLE 1.ANGLE 支持跨平台2.ANGLE 支持渲染器3.ANGLE 下载地址 三.EGL 坐标系四.EGL 绘图步骤五.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录…

第八篇:Spring Boot整合Thymeleaf_入门试炼04

继承parent父工程&#xff0c;新建一个子项目&#xff0c;名称为spring-boot-chapter-8 1、引入 thymeleaf 模板依赖 <!-- 引入 thymeleaf 模板依赖 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-star…

华为发布基于第二代英特尔®至强®可扩展处理器家族的新一代服务器

2019年4月4日&#xff0c;在主题为“智能&#xff0c;计算进化”的发布会上&#xff0c;华为正式发布了基于第二代英特尔 至强 可扩展处理器以及支持英特尔傲腾 ™ 数据中心级持久内存的新一代FusionServerPro智能服务器&#xff0c;包括2路、4路机架式服务器&#xff0c;高密X…

java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä'

java.sql.SQLException: The server time zone value ‘’ is unrecognized or represents more than one time zone. You must configure either the server or JDBC driver (via the serverTimezone configuration property) to use a more specifc time zone value if you w…

第九篇:Spring Boot整合Spring Data JPA_入门试炼01

Spring Data JPA:介绍&#xff1a; Spring Data就是spring提供操作数据库的框架&#xff0c;而Spring Data JPA只是Spring Data框架下的一个基于JPA标准操作数据库的模块。 Spring Data JPA&#xff1a;基于JPA的标准对数据进行操作。简化持久层的代码&#xff0c;只需要写接口…

华为智能计算发布FusionServer Pro智能服务器

【中国&#xff0c;北京&#xff0c;2019年4月3日】华为智能计算业务部在北京召开了主题为“智能&#xff0c;计算进化”的发布会&#xff0c;正式发布FusionServer Pro智能服务器。将从“智能加速、智能管理、智能数据中心”三个层次助力数据中心智能化升级。 世界正从数字化…

分布式精华问答:分布式环境下如何保持数据一致性的?| 技术头条

分布式开发的时代实际上早已悄悄地成为了时代的主流&#xff0c;今天&#xff0c;我们就来看看关于分布式的精华问答吧&#xff01;1Q&#xff1a;分布式系统中主要是用到了服务化&#xff0c;消息中间件&#xff0c;数据库拆分&#xff0c;便于横向扩展和维护&#xff0c;但分…

第九篇:Spring Boot整合Spring Data JPA_入门试炼03

CrudRepository接口的使用 CrudRepository接口&#xff0c;主要完成一些增删改查的操作。 注意&#xff1a;CrudRepository接口继承Repository接口 1、持久层接口&#xff1a; package com.gblfy.repository;import com.gblfy.pojo.Users; import org.springframework.data.r…

第九篇:Spring Boot整合Spring Data JPA_入门试炼04

六、PagingAndSortingRepository接口 前言&#xff1a;该接口提供了分页与排序的操作&#xff0c;该接口继承了CrudRepository 1、持久层接口&#xff1a; public interface UserRepositoryPagingAndSorting extends PagingAndSortingRepository<Users,Integer> { }测试…

成立一周?谷歌人工智能道德委员会解散了?近日,金山云和小米刚签订了不超过9000万的硬件产品供应协议,闹哪样? | 极客头条...

关注并标星星CSDN云计算极客头条&#xff1a;速递、最新、绝对有料。这里有企业新动、这里有业界要闻&#xff0c;打起十二分精神&#xff0c;紧跟fashion你可以的&#xff01;每周三次&#xff0c;打卡即read更快、更全了解泛云圈精彩newsgo go go 亚马逊推Alexa无线耳机&…

2019年技术盘点微服务篇(二):青云直上云霄 | 程序员硬核评测

戳蓝字“CSDN云计算”关注我们哦&#xff01;程序员硬核评测&#xff1a;客观、高效、不说软话。无论是技术质量、性能水平&#xff0c;还是工具筛选&#xff0c;一测便知&#xff01;作者&#xff1a;孙浩峰过去几年来&#xff0c;“微服务架构”方兴未艾&#xff0c;尽管这种…

第九篇:Spring Boot整合Spring Data JPA_入门试炼06

八、JpaSpecificationExecutor接口 前言&#xff1a;该接口主要提供了多条件查询的支持&#xff0c;并且可以在查询中添加分页和排序。 注意&#xff1a;JpaSpecificationExecutor接口是独立存在的。完全独立。 1、持久层接口&#xff1a; public interface UsersRepositoryS…

第十篇:Spring Boot整合mybatis+逆向工程(Mysql+Oracle) 入门试炼01

1、添加pom依赖 <dependencies><!--springboot web 启动器--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--thymeleaf 启动器--><d…

Docker简介与简单使用 | 技术头条

戳蓝字“CSDN云计算”关注我们哦&#xff01;技术头条&#xff1a;干货、简洁、多维全面。更多云计算精华知识尽在眼前&#xff0c;get要点、solve难题&#xff0c;统统不在话下&#xff01;作者&#xff1a;常仕禄转自&#xff1a;Docker前一段花了一段时间研究Log4j2的源码&a…

OpenGL ES EGL eglSwapBuffer

目录 一. EGL 前言二. EGL 绘制流程简介三.eglSwapBuffer 函数简介 四.关于多个 EGLContext五.共享 EGLContext六.猜你喜欢 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> OpenGL ES 基础 零基础 OpenGL ES 学习路线推荐 : OpenGL ES 学习目录 >> Open…