Ts自封装WebSocket心跳重连

WebSocket是一种在单个TCP连接上进行全双工通信的协议,允许客户端和服务器之间进行双向实时通信。

所谓心跳机制,就是在长时间不使用WebSocket连接的情况下,通过服务器与客户端之间按照一定时间间隔进行少量数据的通信来达到确认连接稳定的手段。

Js提供的原生WebSocket的API较为简陋,博主这里对其进行简单封装,使其具有心跳机制。

一、搭建测试用本地服务器

博主使用node.js建立本地WebSocket服务器,代码如下

const WebSocket = require("ws");
const WebSocketServer = WebSocket.Server;
const wss = new WebSocketServer({ port: 3000 });
wss.on("connection", (ws) => {

  ws.on("message", (message, err) => {
    let data=JSON.parse(message.toString())
    console.log(data);
    if (err) {
      console.log(err);
    } else {
      if (data.type == "heartbeat") {
        ws.send(JSON.stringify({ "type": "heartbeat", "data": "---HeartBeatOK---" }));
      } else {
        ws.send(JSON.stringify({ "type": "normal","data": "Receive "+data.data+" OK" }));
      }
    }
  });
});

主要思路为,客户端建立连接后,进入wss.on('connection')的回调函数,开启message的监听。约定:消息为一个JSON字符串,其中包含type和data。

type是字符串类型,只有两个取值,一个是heartbeat,一个是normal。

type字段规定了消息体是心跳消息还是一般消息。

data是实际传输的数据。

这里数据传输遇到一点小问题,JSON字符串在传输过程中被转化为buffer格式,所以在接受message的时候需要调用toString方法转化为JSON字符串,然后才能用JSON.parse把内容解析出来。

如果心跳消息正常接受,服务器返回“---HeartBeatOK---”;如果一般消息正常接受,服务器返回“Receive ”(消息体)“ OK”。

二、进行WebSocket的封装

实现心跳的思路为,每隔一段时间(记为pingTimeOut),客户端发送数据到服务器,然后开始等待,如果等待时间超出规定时间(记为pongTimeOut),就启动重连函数,否则清空当前计时器。

值得注意的是,重连函数中应该设置重连的时间间隔,不然可能会因为多次连续重连报错。

首先建立一个参数协议

export interface OPTS {
  url: string;
  pingTimeOut?: number;
  pongTimeOut?: number;
  reconnectTimeOut?: number;
}

里面是我们可能需要修改的数值。其中url为必填,是WebSocket服务器的地址,reconnectTimeOut是连续重连的间隔时间。

export default class Websocket {
  private opts: OPTS;
  private ws: WebSocket;
  private lockReconnect: boolean = false;
  private forbidReconnect: boolean = false;
  private heartBeatTimer;
  private serverReplyTimer;
  constructor({
    url,
    pingTimeOut = 15000,
    pongTimeOut = 10000,
    reconnectTimeOut = 2000,
  }) {
    this.opts = {
      url: url,
      pingTimeOut: pingTimeOut,
      pongTimeOut: pongTimeOut,
      reconnectTimeOut: reconnectTimeOut,
    };
    this.createWebSocket();
  }

​

构造函数中传入我们需要的数值,非必填项设置默认值,将其赋给opts,然后调用createWebSocket方法。这个方法会在下文实现。首先,设置ws变量装载WebSocket示例对象,

设置lockReconnect,这个值用来控制:当重连程序运行中,不会再次触发重连程序。

forbidReconnect则是用来控制重连程序,当我们手动调用停止WebSocket连接的时候,禁止自动重连。

​createWebSocket() {
    try {
      this.ws = new WebSocket(this.opts.url);
      this.EventHandler();
    } catch (e) {
      console.log("create",e);
      this.reconnect();
    }
  }

​

这里创建了一个WebSocket实例对象,传入opts参数中的url。

EventHandler() {
    this.ws.onerror = (e) => {
      console.log(e);
      this.reconnect();
    };
    this.ws.onmessage = (e) => {
      let result = JSON.parse(e.data).data;
      console.log(result);
      if (result == "---HeartBeatOK---") {
        clearTimeout(this.serverReplyTimer)
      }
    };
    this.ws.onopen = (e) => {
      this.startHeartBeat();
    };
    this.ws.onclose = (e) => {
      console.log(e);
      this.reconnect()
    };
  }

这里设置了所有当前监听ws状态变化的回调函数,其中,在onmessage回调函数中,如果收到服务器传来的心跳确认,就清除服务器回复计时器。之后的业务逻辑也可以在这里进行处理,或者另外封装业务处理函数,放在这里调用。

在onopen函数中开启心跳。

其余两种非正常状态,输出错误信息后启动重连程序。

心跳函数细节如下:

  startHeartBeat() {
    if (this.heartBeatTimer) clearInterval(this.heartBeatTimer)
      console.log("start heart beat");
      this.ws.send(JSON.stringify({ type: "heartbeat", data: "-_-" }));
      this.heartBeatTimer = setInterval(() => {
        this.ws.send(JSON.stringify({ type: "heartbeat", data: "-_-" }));
      }, this.opts.pingTimeOut);
  }

如果创建过心跳计时器,但是由于重连的原因,重新开始心跳,就清除原来的计时器,重新创建一个心跳计时器。创建前需要立即发送一次心跳信号。计时器的时间间隔为opts中的参数。

  reconnect() {
    clearInterval(this.heartBeatTimer)
    if (!this.lockReconnect && !this.forbidReconnect) {
      this.lockReconnect = true;
      setTimeout(() => {
        this.createWebSocket();
        this.lockReconnect = false;
      }, this.opts.reconnectTimeOut);
    }
  }

重连,清除心跳计时器,如果正在执行重连(lockReconnect控制),或者已经手动关闭连接,就直接退出。

经过规定时间(参数为连续重连的时间间隔)后重新创建WebSocket实例对象。

 close() {
    this.ws.close();
    clearInterval(this.heartBeatTimer)
    this.forbidReconnect = true;
  }

手动关闭WebSocket连接的函数,设置禁用自动连接。同时清除心跳计时器。

博主使用Cocos进行测试,设置每次点击按钮传输0-9随机数字,同时每隔3秒进行一次心跳通信。

可以看到心跳通信正常,同时还可以进行数据传输。

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

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

相关文章

大模型微调LoRA训练与原理

1.什么是LoRA? LoRA的全称是LOW-RANK-ADAPTATION。是一种实现迁移学习的技术手段。 2. 矩阵的秩? 秩是一个向量空间的基向量的个数。例如:二维平面坐标系存在两个基向量,平面上任意的一个向量都可以使用这两个基向量进行线性表示…

PS制作淘宝主图

PS制作淘宝主图 1.制作主图主页1.1新建800x800画板1.2填充前景色:altdel1.3选择圆角矩形,半径501.4按住ALT,往下投复制 2.调色 1.制作主图主页 1.1新建800x800画板 1.2填充前景色:altdel 1.3选择圆角矩形,半径50 居中对…

矿用以太网通讯的电缆传输可行性分析

概述 井下通讯系统是煤矿安全及生产调度必不可少的设施,近年泄露技术、小灵通技术、无线对讲技术及WIFI技术相继应用于煤矿井下。WIFI技术在地面的短距离无线通讯中已有多年的应用,相对于其他的无线宽带技术来说比较成熟可靠。 “泄露”技术及低频穿透技…

VC2019更改文件名称代码

VC2019更改文件名称代码 效果代码 效果 华为手机拍摄的视频默认名称是“VID_20231213_111723”,图片名称是“IMG_20231213_111723”,需要批量将“VID”改为“IMG” 代码 代码(C#): csharpStringBuilder sbnew StringBuilder()…

ROS TF坐标变换 - 静态坐标变换

目录 一、静态坐标变换(C实现)二、静态坐标变换(Python实现) 如前文所属,ROS通过广播的形式告知各模块的位姿关系,接下来详述这一机制的代码实现。 模块间的位置关系有两种类型,一种是相对固定…

使用spring boot实现异常的统一返回

在这个前后端分离的时代,一个 统一的数据格式非常重要。本次我们实现用spring boot实现一下返回给前端数据的统一格式,不再出现服务器500的错误。 新建一个spring boot项目,并导入knife4j的依赖。 写一个controller控制器,用来是…

Vue中全局事件总线的配置和原理

实现任意组件之间的通信 任意组件通信的原理: 1、实现任意组件之间的通信,需要一个傀儡。这个傀儡既能被vm访问到,也能被VueComponent访问。 2、VueComponent.prototype.proto Vue.prototype为图上1.0黄色的线路。是Vue让组件实例对象VueComponent可以访问到Vue原…

将学习自动化测试时的医药管理信息系统项目用idea运行

将学习自动化测试时的医药管理信息系统项目用idea运行 背景 学习自动化测试的时候老师的运行方式是把医药管理信息系统项目打包成war包后再放到tomcat的webapp中去运行,于是我想着用idea运行会方便点,现在记录下步骤方便以后查找最开始没有查阅资料&am…

【栈】根据模式串构造最小数字

import java.util.ArrayDeque; import java.util.Deque;/*** 思路:如果是字符‘I’直接对应的数字加入结果res中,如果是‘D’将对应的数字加入栈中。* 再次遇到‘I’先将对应的数字加入结果res中,然后再将栈中的元素从栈顶取出存放在* …

simulink代码生成(五)——ePWM模块初级应用

前面分别讲到了SCI及ADC的配置及使用,现在梳理一下ePWM的配置和使用; 先打一些基础的DSP28335的基础知识; F28335 关于ePWM中断与SOC采样信号的一些思考_socasel-CSDN博客 F28335 ePWM模块简介——TMS320F28335学习笔记(四&…

受“博比特虫”启发可实现多模态传感抓取动作的软执行器来了

软执行器可以实现对易碎和不规则形状物体的精细自适应抓取,这在生物和工程系统中至关重要。然而,目前软机器人在抓取的时候往往受制于抓取能力不足和功能限制。 博比特虫捕获猎物 最近研究人员提出了一种受博比特虫启发的多模态传感自适应软抓取器&…

simulink代码生成(六)——多级中断的配置

假如系统中存在多个中断,需要合理的配置中断的优先级与中断向量表;在代码生成中,要与中断向量表对应;中断相关的知识参照博客: DSP28335学习——中断向量表的初始化_中断向量表什么时候初始化-CSDN博客 F28335中断系…

sscanf的简介

sscanf 函数的原型: 第一个函数参数 const char * 表示字符串 (类似于scanf)第二个函数参数表示 格式 ​​​​​​​ ​​​​​​​ 第三个函数参数 首先sscanf函数可以用于以下几种情况: 分离数字: #i…

Java开发过程中的幂等性问题

幂等性问题: 1. 有时我们在填写某些 form表单 时,保存按钮不小心快速点了两次,表中竟然产生了两条重复的数据,只是id不一样。 2. 我们在项目中为了解决 接口超时 问题,通常会引入了 重试机制 。第一次请求接口超时了…

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项样题卷①

2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项(高职组) 样题(第1套) 目录 2023年“中银杯”四川省职业院校技能大赛“云计算应用”赛项(高职组) 样题(第1套) 模块一…

消息队列LiteQueue

文章目录 一、简介二、设计2.1 队列结构设计2.2 队列接口设计 三、实现3.1 队列锁的实现3.2 创建队列3.3 写入队列3.4 读出数据3.5 判断队列是否为空3.6 判断队列是否为满3.7 清空队列3.8 删除队列 四、测试参考 一、简介 收到消息时先把接收到的消息放到队列中。在任务中从队…

[NAND Flash 4.2] Flash 原理 | NOR Flash 和 NAND Flash 闪存详解

依公知及经验整理,原创保护,禁止转载。 专栏 《深入理解NAND Flash》 <<<< 返回总目录 <<<< 前言 智能手机有一个可用的存储空间(如苹果128G),电脑里有一个固态硬盘空间(如联想512G), 这个空间是啥呢? 这个存储空间就是闪存设备,我们都统称为…

计算机网络课程设计-企业网三层架构

&#xff08;单人版&#xff09; 摘 要 本篇报告主要解决了为一家名为西宫的公司网络搭建问题&#xff0c;该网络采用企业网三层架构对完了过进行设计。首先使用以太网中继&#xff0c;主要使用VLAN划分的技术来划定不同部门。使用MSTP对每个组配置生成树&#xff0c;防止交换机…

华为交换机生成树STP配置案例

企业内部网络怎么防止网络出现环路&#xff1f;学会STP生成树技术就可以解决啦。 STP简介 在二层交换网络中&#xff0c;一旦存在环路就会造成报文在环路内不断循环和增生&#xff0c;产生广播风暴&#xff0c;从而占用所有的有效带宽&#xff0c;使网络变得无法正常通信。 在…

【JVM】一文掌握JVM垃圾回收机制

作为Java程序员,除了业务逻辑以外,随着更深入的了解,都无法避免的会接触到JVM以及垃圾回收相关知识。JVM调优是一个听起来很可怕,实际上很简单的事。 感到可怕,是因为垃圾回收相关机制都在JVM的C++层实现,我们在Java开发中看不见摸不着;而实际很简单,是因为它说到底,也…
最新文章