爱智EdgerOS之深入解析在爱智应用中如何使用Socket.IO轻松实现双向通信

news/2024/5/6 14:22:55/文章来源:https://blog.csdn.net/Forever_wj/article/details/130118917

一、什么是 Socket.IO?

  • Socket.IO 是一个基于事件通信的实时应用程序框架,它在即时通讯、通知和消息推送,实时分析等场景中有广泛的应用。
  • Socket.IO 包括两个部分:
    • 在 Server 端的模块(JSRE 已提供了 socket.io 模块);
    • 在 Client 端的模块。
  • Socket.IO 将实现分成了两层:
    • 底层管道:即 Engine.IO 层,它是 Socket.IO 的内部引擎。
    • 高级API:即 Sokcet.IO 本身。
  • Engine.IO 负责建立服务器和客户端之间的低级连接,它的主要任务是处理各种传输和升级机制以及断线检测重连。客户端首先会尝试通过 WebSocket 进行连接,如果失败则会回退到 HTTP 进行长轮询。所以,理想情况下应该保证:
    • 浏览器是支持 WebSocket 的;
    • 没有任何元素(代理、防火墙等)阻止客户端和服务器之间的 WebSocket 连接。
  • 当连接建立完成之后,高层就可以通过暴露出来的 API 进行数据交换。

二、高层API

  • Socket.IO 是基于事件的,实际上就是对 EventEmitter 类的继承,在 EventEmitter 中,对象(发射器)发出命名事件,导致函数对象(侦听器)被调用。基于事件驱动,需要通过 on 方法向侦听器中添加事件名以及监听函数,通过 emit 来触发监听函数,从而完成通信任务。
  • Socket.IO 实现了 EventEmitter 中的事件触发以及监听函数,包括基本的 on(), emit(), removeListener() 等,同时也自定义了一些针对连接生命周期内的事件名,包括:
    • connect 来自客户端连接时触发;
    • connection 是 connect 的别名;
    • disconnect 断开连接时触发;
    • disconnecting 当客户端将要断开连接(还未离开 rooms)时触发;
    • error 发生错误时触发。
  • 这些是 Socket.IO 的保留字段(还有 newListener,removeListener),在自定义的时候应该避免和这些字段重名。

三、JSRE 中的引用

  • JSRE 中提供了 Socket.IO 的模块,在服务端可以直接使用,需要注意的是当前 JSRE 中 Socket.IO 的版本为 2.x,前端在使用 Socket.IO 的模块时需要注意版本对应。
  • 那么 Socket.IO 是如何运行的呢?

四、Server 端的创建

  • 如下所示,是 Server 端的示例代码:
/* Import system modules */
const WebApp = require('webapp');
const io = require('socket.io');/* Import routers */
const myRouter = require('./routers/rest');/* Create App */
const app = WebApp.createApp();/* Set static path */
app.use(WebApp.static('./public'));/* Set test rest */
app.use('/api', myRouter);/* Rend test */
app.get('/temp.html', function(req, res) {res.render('temp', { time: Date.now() });
});/* Start App */
app.start();const socketio = io(app, {serveClient: false,pingInterval: 10000,pingTimeout: 5000
})socketio.on('connection', socket => {console.log('>> socket connected <<')socket.emit('falcon', 'reply please')socket.on('message', (data, ack) => {console.log('recive:', data)ack('0')})socket.on('message2', data => {console.log('recive:', data)})
})/* Event loop */
require('iosched').forever();
  • 可以看到,创建 Socket.IO 的 server 还是很简单的,只需要将 webapp 的实例作为参数传递进去,然后监听 connection 方法。emit 会发射消息,消息内容可以根据自己的需求定义,可以是简单的字符串,也可以是一个结构化的 JSON 对象。
  • 在 socket.on 中定义监听消息字段,如上示例,我们可以仅仅接收数据,进行处理,也可以给出 ack 返回确认信息。socket.emit 同样支持 response 的返回函数,以做出确认响应。
socket.emit('ferret', 'tobi', (data) => {console.log(data); // data will be 'woot'
});// client code example
client.on('ferret', (name, fn) => {fn('woot');
});

五、Client 端的创建

  • 接下来看一下前端应用如何使用使用 Socket.IO 与服务端的建立连接并通信,以 Vue3 为例,使用 socket.io-client 包:
npm install socket.io-client
# or use yarn 
yarn add socket.io-client
  • 为了方便在不同的页面进行调用,可以将 socket.io 进行一次封装,以下仅作为参考:
// src/libs/socketio.js
import io from 'socket.io-client'
class SocketIO {constructor () {this.socket = io('https://192.168.128.1:7369')this.socket.on('connect', () => {// 连接上服务端的回调函数// 还可以监听 'error' 并对错误连接进行相应处理console.log('>> 已连接!')})}push (event, msg) {// 这里封装了一个通用 response 的 emit 方法用以处理相同确认操作的 emitthis.socket.emit(event, msg, (response) => {console.log('>>>> res:', response)})}
}export const socketio = new SocketIO()

六、客户端连接生命周期

  • 生命周期示意图:

在这里插入图片描述

  • 接下来在不同的页面就可以引用这个封装来进行简单操作:
// src/App.jsx
import { defineComponent, onMounted } from 'vue'
import './app.less' // css 设置白色背景及安全距离
// 上文中导出的 socketio
import { socketio } from './libs/socketio'export default defineComponent({name: 'APP',setup (props, ctx) {//onMounted(() => {// 如果此页面需要监听后端发送数据// 最好将监听函数在 onMounted 生命周期中创建出来socketio.socket.on('message', data => {console.info('>> client recive:', data)})})// 发送数据的函数function handleEmitMsg () {socketio.push('message', 'gg')}return () => (<div><p><button onClick={ handleEmitMsg }>emit</button></p></div>)}
})
  • 以上就是前端监听消息,以及发送消息的操作,如果此时想对特定操作执行 emit 消息返回确认,可以从实例中获取:
// 修改上例中的 emit 函数
// 发送数据的函数
function handleEmitMsg () {socketio.socket.emit('message', 'data', response => {// 逻辑代码})
}
  • 至此已经完整走完 Socket.IO 的建立过程,理解的点就在于需要知道 socket 是一个基于事件双向通信的过程,两端都可以进行主动消息的发送以及被动消息的接收,所以需要事先约定好一个消息名称,作为消息发送方,需要 emit 发送这个消息;作为消息接收方,需要 on 接收这个消息。

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

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

相关文章

UPA/URA双极化天线的协方差矩阵结构

文章目录UPA的阵列响应向量&#xff08;暂不考虑双极化天线&#xff09;UPA阵列响应&#xff1a;从单极化天线到双极化天线UPA双极化天线的协方差矩阵结构参考文献UPA的阵列响应向量&#xff08;暂不考虑双极化天线&#xff09; 下图形象描述了UPA阵列的接收信号 UPA阵列的水平…

已知原根多项式和寄存器初始值时求LFSR的简单例子

线性反馈移位寄存器&#xff08;LFSR&#xff09;是一种用于生成伪随机数序列的简单结构。在这里&#xff0c;我们有一个四项原根多项式 p(x)1x0x21102p(x) 1 x 0x^2 110_2p(x)1x0x21102​ 和初始值 S0100S_0 100S0​100。我们将使用 LFSR 动作过程来生成一个伪随机序列。…

SpringBoot【运维实用篇】---- SpringBoot程序的打包与运行

SpringBoot【运维实用篇】---- SpringBoot程序的打包与运行程序打包程序运行SpringBoot程序打包失败处理命令行启动常见问题及解决方案刚开始做开发学习的小伙伴可能在有一个知识上面有错误的认知&#xff0c;我们天天写程序是在Idea下写的&#xff0c;运行也是在Idea下运行的。…

vue——项目中加载public中的静态资源——技能提升

应用场景 在写后台管理系统的时候&#xff0c;遇到一个需求就是关于热力图的功能&#xff0c;需要加载不同的页面&#xff0c;这个页面需要每日更新一次&#xff0c;所以请求页面html的最终解决办法就是&#xff1a;将页面html对应的文件夹&#xff0c;放在public文件夹中&…

Zephyr RTOS应用开发(nrf5340)

目录 概述 开发环境安装 创建一个新的Zephyr应用 构建应用并刷写到开发板 概述 Zephyr™项目是一个采用Apache 2.0协议许可&#xff0c;Linux基金会托管的协作项目。针对低功耗、小型内存微处理器设备开发的物联网嵌入式小型、可扩展的实时操作系统&#xff0c;支持多种硬件…

(八)【软件设计师】计算机系统—浮点数

浮点数 浮点数。当机器字长为n时&#xff0c;定点数的补码和移码可表示2的n方个数&#xff0c;而其原码和反码只能表示2"-1个数&#xff08;0的表示占用了两个编码)&#xff0c;因此&#xff0c;定点数所能表示的数值范围比较小&#xff0c;在运算中很容易因结果超出范围而…

JavaScript -- 对象

1. 概念 对象是 JavaScript 数据类型的一种&#xff0c;可以理解为是一种无序的数据集合 2. 对象的使用 2.1 对象的声明 let 对象名 {} let 对象名 new Object() 2.2 属性和方法 数据描述性的信息称为属性&#xff0c;如人的姓名、身高、年龄、性别等&#xff0c;一般是…

前端项目-12-个人中心-二级路由配置-导航守卫-懒加载

目录 1-个人中心 1.1-个人中心路由注册 1.2-拆分二级路由组件 1.3-动态渲染我的订单页面 2-导航守卫优化 2.1-用户未登录导航守卫优化 2.2-路由独享 2.3-组件内守卫 3-懒加载 3.1-图片懒加载 3.2-路由懒加载 4-map文件处理 1-个人中心 需求&#xff1a;当用户点击支…

DevOps实践分享:4个实施步骤与6个关键设计

本文介绍了普元DevOps平台在金融行业实施落地的常用方法&#xff0c;以及在项目管理&#xff0c;代码管理&#xff0c;构建管理&#xff0c;制品管理&#xff0c;部署管理等模块针对一些典型客户场景的关键设计。目 录01 平台简介‍‍02 实施方法‍‍‍‍‍‍03 关键设计01平…

OceanBase 4.1 发版 | 一个面向开发者的里程碑版本

欢迎访问 OceanBase 官网获取更多信息&#xff1a;https://www.oceanbase.com/ 2022 年 8 月&#xff0c;OceanBase发布了 4.0 版本&#xff08;小鱼&#xff09;&#xff0c;作为业内首个单机分布式一体化架构&#xff0c;兼顾了分布式架构的扩展性和集中式架构的性能优势&…

算法:链表和数组哪个实现队列更快

背景 对于这个问题&#xff0c;我们先来思考一下数组和链表各有什么特点。 数组&#xff1a;连续存储&#xff0c;push 很快&#xff0c;shift 很慢。 链表&#xff1a;非连续存储&#xff0c;add、delete 都很快&#xff0c;但是查找很慢。 所以&#xff0c;我们可以得出结论…

TCP/UDP协议 (详解)

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了 博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点!人生格言&#xff1a;当你的才华撑不起你的野心的时候,你就应该静下心来学习! 欢迎志同道合的朋友一起加油喔&#x1f9be;&am…

49天精通Java,第26天,LinkedHashSet、LinkedHashMap、EnumSet、EnumMap

目录一、链接散列集LinkedHashSet二、链接散列映射LinkedHashMap三、枚举集EnumSet1、EnumSet2、枚举集可以用来实现一些特殊的功能&#xff0c;例如&#xff1a;3、枚举集的常用方法包括&#xff1a;四、枚举映射EnumMap1、EnumMap2、枚举映射可以用来实现一些特殊的功能&…

基于朴素贝叶斯分类器的钞票真伪识别模型

基于朴素贝叶斯分类器的钞票真伪识别模型 内容 本实验通过实现钞票真伪判别案例来展开学习朴素贝叶斯分类器的原理及应用。 本实验的主要技能点&#xff1a; 1、 朴素贝叶斯分类器模型的构建 2、 模型的评估与预测 3、 分类概率的输出 源码下载 环境 操作系统&#xf…

springboot学习2

一、spring boot自动装配原理 pom.xml spring-boot-dependencies 核心依赖在父工程中 在写或者引入一些spring boot依赖的时候&#xff0c;不需要指定版本&#xff0c;因为有这些版本仓库启动器 <dependency><groupId>org.springframework.boot</groupId>&…

数据结构刷题笔记 | 数组、字符串、链表、栈、队列、数、图

本篇为笔者学习数据结构时&#xff0c;在牛客网站的刷题笔记。 数组——长度固定 数组是一种对象&#xff0c;不属于原生类&#xff0c;数组的大小确定之后不可改变。【原生类指未被实例化的类&#xff0c;数组一般指实例化&#xff0c;被分配空间的类】数组常用的两种基本操作…

C#,码海拾贝(18)——矩阵的(一般)三角分解法(Triangular Decomposition)之C#源代码,《C#数值计算算法编程》源代码升级改进版

1 三角分解法 Triangular Decomposition 三角分解法亦称因子分解法&#xff0c;由消元法演变而来的解线性方程组的一类方法。设方程组的矩阵形式为Axb&#xff0c;三角分解法就是将系数矩阵A分解为一个下三角矩阵L和一个上三角矩阵U之积&#xff1a;ALU&#xff0c;然后依次解…

数字化体验时代,企业如何做好内部知识数字化管理

随着数字化时代的到来&#xff0c;企业内部的知识管理也面临着新的挑战和机遇。数字化技术的应用&#xff0c;可以极大地提高企业内部知识的数字化管理效率和质量&#xff0c;从而提升企业内部的工作效率、员工满意度和企业竞争力。本文将从数字化时代的背景出发&#xff0c;探…

大数据 | HBase基本工作原理

前文回顾&#xff1a;MapReduce基本原理 目录 &#x1f4da;HBase基本介绍 &#x1f407;HBase的设计目标和功能特点 &#x1f407;HBase在Hadoop中的生态环境 &#x1f4da;HBase的数据模型 &#x1f407;逻辑数据模型 &#x1f407;物理存储格式 &#x1f4da;HBase基…

使用golang连接kafka

1 下载&#xff0c;配置&#xff0c;启动 kafka 下载链接 配置修改 在config目录下的server文件和zookeeper文件&#xff0c;其中分别修改kafka的日志保存路径和zookeeper的数据保存路径。 启动kafka 先启动kafka自带的zookeeper&#xff0c;在kafka的根目录下打开终端&a…