位置: IT常识 - 正文

WebSocket的心跳机制和断线重连(netty websocket心跳)

编辑:rootadmin
WebSocket的心跳机制和断线重连 背景

推荐整理分享WebSocket的心跳机制和断线重连(netty websocket心跳),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:netty websocket心跳,socketio心跳,spring boot websocket 心跳机制,socket 心跳,swoole websocket心跳,websocket服务端心跳检测,websocket服务端心跳检测,websocket的心跳机制,内容如对您有帮助,希望把文章链接给更多的朋友!

在服务器重启或是弱网情况下,前端不能保证一直连接成功。因此在出现被动断开的情况下,需要有心跳机制和断线重连的功能。

心跳机制:客户端每隔一段时间向服务端发送一个特有的心跳消息,每次服务端收到消息后只需将消息返回,此时,若二者还保持连接,则客户端就会收到消息,若没收到,则说明连接断开,此时,客户端就要主动重连,完成一个周期

断线重连:若某时间段内客户端发送了消息,而服务端未返回,则认定为断线;这个时候会触发到websocket中的onclose事件,需要重新连接服务

nodejs+ws模块搭建websocket服务器

之前我有篇文章使用的是nodejs+websocket模块搭建的服务器,后来发现ws模块更易使用和社区一直有人维护,因此推荐使用ws模块

下载ws依赖 ws - npm

npm i wsWebSocket的心跳机制和断线重连(netty websocket心跳)

在文件夹下新增server.js文件

/* server.js 服务器 */// 引入模块const WebSocket = require('ws').Serverconst port = 8002// 创建服务器const server = new WebSocket({ port }, () => { console.log('websocket服务开启')})const connectHandler = (ws) => { console.log('客户端连接') // 监听客户端出错 ws.on('error', errorHandler) // 监听客户端断开链接 ws.on('close', closeHandler) // 监听客户端发来的消息 ws.on('message', messageHandler)}// 监听接收客户端信息回调// 注意:因为这里用到this的指向,因此用普通的函数function messageHandler(data) { console.log('messageHandler===>接收客户端消息', JSON.parse(data)) const { ModeCode } = JSON.parse(data) switch(ModeCode) { case 'message': console.log('收到消息') // 需要发送信息给客户端以此说明连接成功 this.send(JSON.stringify(JSON.parse(data))) break; case 'heart_beat': console.log('心跳检测') // 需要发送信息给客户端以此说明连接成功 this.send(JSON.stringify(JSON.parse(data))) break; }}// 监听客户端出错回调const errorHandler = (error) => { console.log('errorHandler===>客户端出错', error)}// 监听客户端断开连接回调const closeHandler = (e) => { console.log('closeHandler===>客户端断开🔗', e)}// 建立连接server.on('connection', connectHandler)客户端的实现

1. 封装websocket,需要实现心跳机制和断线重连

2. 封装自定义通信事件,实现监听和触发功能

在文件夹下新增eventBus.js文件

// eventBus.js// 用到了发布订阅模式class EventBus { constructor() { // 消息中心,记录了所有的事件 以及 事件对应的处理函数 this.subs = Object.create(null) } // 注册时间 // 参数:1.事件名称 2.事件处理函数 on(eventType, handler) { this.subs[eventType] = this.subs[eventType] || [] this.subs[eventType].push(handler) } // 触发事件 // 参数: 1.事件名称 2.接收的参数 emit(eventType, ...ars) { if(this.subs[eventType]) { this.subs[eventType].forEach(handler => { handler(...ars) }) } }}export default new EventBus()

在文件夹下新增myWebSocket.js文件

// myWebSocket.js 单独把websocket的处理方法抽离出来import eventBus from "./eventBus.js"// 定义websocket消息类型const ModeCodeEnum = { MSG: 'message', // 普通消息 HEART_BEAT: 'heart_beat' // 心跳}class MyWebSocket extends WebSocket { constructor (url) { super(url) return this } /** * heartBeatConfig 心跳连接参数 * time: 心跳时间间隔 * timeout: 心跳超时间隔 * reconnect: 断线重连时间间隔 * isReconnect 是否断线重连 */ init (heartBeatConfig, isReconnect) { this.onopen = this.openHandler // 连接成功后的回调函数 this.onclose = this.closeHandler // 连接关闭后的回调 函数 this.onmessage = this.messageHandler // 收到服务器数据后的回调函数 this.onerror = this.errorHandler // 连接发生错误的回调方法 this.heartBeatConfig = heartBeatConfig // 心跳连接配置参数 this.isReconnect = isReconnect // 记录是否断线重连 this.reconnectTimer = null // 记录断线重连的时间器 this.startHeartBeatTimer = null // 记录心跳时间器 this.webSocketState = false // 记录socket连接状态 true为已连接 } // 获取消息 getMessage ({ data }) { return JSON.parse(data) } // 发送消息 sendMessage (data) { // 当前的this 就是指向websocket return this.send(JSON.stringify(data)) } // 连接成功后的回调函数 openHandler () { console.log('====onopen 连接成功====') // 触发事件更改按钮的状态 eventBus.emit('changeBtnState', 'open') // socket状态设置为连接,做为后面的断线重连的拦截器 this.webSocketState = true // 判断是否启动心跳机制 if(this.heartBeatConfig && this.heartBeatConfig.time) { this.startHeartBeat(this.heartBeatConfig.time) } } // 收到服务器数据后的回调函数 messageHandler (data) { const { ModeCode, msg} = this.getMessage(data) switch (ModeCode) { case ModeCodeEnum.MSG: // 普通消息类型 console.log('====onmessage 有新消息啦====', msg) break case ModeCodeEnum.HEART_BEAT: // 心跳 this.webSocketState = true console.log('====onmessage 心跳响应====', msg) break } } // 连接关闭后的回调 函数 closeHandler () { console.log('====onclose websocket关闭连接====') // 触发事件更改按钮的状态 eventBus.emit('changeBtnState', 'close') // 设置socket状态为断线 this.webSocketState = false // 在断开连接时 记得要清楚心跳时间器和 断开重连时间器材 this.startHeartBeatTimer && clearTimeout(this.startHeartBeatTimer) this.reconnectTimer && clearTimeout(this.reconnectTimer) this.reconnectWebSocket() } errorHandler () { console.log('====onerror websocket连接出错====') // 触发事件更改按钮的状态 eventBus.emit('changeBtnState', 'close') // 设置socket状态为断线 this.webSocketState = false // 重新连接 this.reconnectWebSocket() } // 心跳初始化方法 time:心跳间隔 startHeartBeat (time) { this.startHeartBeatTimer = setTimeout(() => { // 客户端每隔一段时间向服务端发送一个心跳消息 this.sendMessage({ ModeCode: ModeCodeEnum.HEART_BEAT, msg: Date.now() }) this.waitingServer() }, time); } //在客户端发送消息之后,延时等待服务器响应,通过webSocketState判断是否连线成功 waitingServer () { this.webSocketState = false setTimeout(() => { // 连线成功状态下 继续心跳检测 if(this.webSocketState) { this.startHeartBeat(this.heartBeatConfig.time) return } console.log('心跳无响应, 已经和服务端断线') // 重新连接时,记得要先关闭当前连接 try { this.close() } catch (error) { console.log('当前连接已经关闭') } // // 重新连接 // this.reconnectWebSocket() }, this.heartBeatConfig.timeout) } // 重新连接 reconnectWebSocket () { // 判断是否是重新连接状态(即被动状态断线),如果是主动断线的不需要重新连接 if(!this.isReconnect) { return } // 根据传入的断线重连时间间隔 延时连接 this.reconnectTimer = setTimeout(() => { // 触发重新连接事件 eventBus.emit('reconnect') }, this.heartBeatConfig.reconnect) }}export default MyWebSocket

在文件夹下新增index.html文件,引入eventBus.js和myWebSocket.js 文件

<html lang="en"><body> <div> <button id="connect">连接</button> <button disabled id="sendMessage">发送</button> <button disabled id="close">关闭</button> </div></body></html><script type="module"> import eventBus from './eventBus.js' import MyWebsocket from './myWebSocket.js' const connectBtn = document.getElementById('connect') const sendMessageBtn = document.getElementById('sendMessage') const closeBtn = document.getElementById('close') const wsUrl = 'ws://127.0.0.1:8002' let myWS = null // // 用来记录是否连接了websocket // 处理下按钮的状态,连接情况下才能有发送和关闭功能,关闭情况下只能有连接功能 const setButtonState = (state) => { switch(state) { case 'open': connectBtn.disabled = true sendMessageBtn.disabled =false closeBtn.disabled = false break case 'close': connectBtn.disabled = false sendMessageBtn.disabled = true closeBtn.disabled = true } } // 连接websocket处理函数 const connectWeboSocket = () => { myWS = new MyWebsocket(wsUrl) // 调用实例对象的init函数 myWS.init({ time: 4 * 1000, timeout: 2 * 1000, reconnect: 3 * 1000 }, true) } // 重新连接webscoket处理 函数 const reconnectWebSocket = () => { // 判断是否有初始化websocket if(!myWS) { connectWeboSocket() return } // 判断实例上的reconnectTimer 是否有值,要记得清除后再连接 if(myWS && myWS.reconnectTimer) { clearTimeout(myWS.reconnectTimer) myWS.reconnectTimer = null connectWeboSocket() } } // 注册设置按钮样式 eventBus.on('changeBtnState', setButtonState) // 注册重连websocket 事件 eventBus.on('reconnect', reconnectWebSocket) // 点击连接按钮 连接websocket服务器 connectBtn.addEventListener('click', reconnectWebSocket) // 点击发送按钮 向服务端传送数据 sendMessageBtn.addEventListener('click', e => { myWS.sendMessage({ ModeCode: "message", msg: 'hello world' }) }) // 点击关闭按钮 断开连接 closeBtn.addEventListener('click', e => { myWS.close() myWS = null })</script>实现心跳机制和断线重连总结

心跳机制的实现,在客户端连接成功的回调中即开启心跳。心跳处理函数内部使用定时器延时触发向服务端发送消息的方法,待服务器将消息返回证明是连线成功状态下,继续调用心跳检测方法。

如果客户端给服务端发送心跳消息,在定义的超时时间后客户端没有收到回复,则说明和服务端断线了,此时会触发到客户端连接关闭的回调函数,在此回调中发起重新连接websocket,如果连接失败继续会触发客户端连接关闭的回调函数继续发起重新连接(如此循环)。

等断线重新连接起来时,在客户端连接成功的回调中又开始了心跳检测。其实就是通过延时的定时器反复以上的操作来和服务端一直通信保持连接。

本文链接地址:https://www.jiuchutong.com/zhishi/290896.html 转载请保留说明!

上一篇:YOLOv5 以txt 或json格式输出预测结果(yolo xml转txt)

下一篇:韦尼格罗德的圣诞市场,德国萨克森-安哈尔特州 (© Krzysztof Baranowski/Moment/Getty Images)(韦罗尼卡)

  • 个人所得税如何计算
  • 开票人和复核人收款人能是一个人吗
  • 苗圃公司会计分录
  • 母子公司的关联交易怎么看
  • 公司车维修费
  • 社保利息计入什么科目
  • 延期申报预缴税款比例
  • 产品不合格造成客户损失怎么赔付
  • 异地学习期间产生的餐费住宿费怎么做账?
  • 公司的利润怎样分配
  • 发生工伤事故借条怎么写
  • 已抵扣红字发票信息表怎么开
  • 税负率是税率吗
  • 二手房增值营业税
  • 年底没有取得发票企业所得税
  • 公司注销过了公示期不去有问题
  • 劳务外包业务外包的区别
  • 印花税申报数据来源
  • 帮别的公司代销产品,对方公司不开具发票怎么做帐
  • 餐饮业代金券怎么用
  • cdr插件哪个最好用
  • 企业所得税避税的方法
  • kb4507449安装失败
  • 2019年下半年中小学教师资格考试综合素质试题
  • 绿萝可以放卧室吗晚上睡觉对人害吗
  • 在web页面中如果出现html语句
  • php调用soap
  • 材料分配的四个步骤
  • 收到银行本票的账务处理
  • post请求怎么用
  • javatoken生成机制
  • php的mysql_query
  • php背景图片代码
  • 增值税一般纳税人是什么意思
  • 红字发票账务处理
  • read命令功能
  • 保险公司的应收账款有哪些
  • 个人注册投资有限公司
  • 确认递延所得税资产时,应估计相关可抵扣
  • 哪些企业不需要做安评
  • sql执行顺序优先级
  • 支付劳务费会计科目怎么写
  • 管理费用主要包括
  • 银行对帐单
  • 主营业务收入净额在利润表里怎么看
  • 分支机构注销后往来账如何处理?
  • 出口退税三类企业影响
  • 软件退税款会计如何处理
  • 结转以后年度抵免的境外所得税怎么进行会计处理
  • 进项票未认证就申报抵扣
  • 商业承兑汇票怎么接收
  • 公司借给股东钱
  • 房地产经纪公司排名
  • 美元利息结汇时结汇项目是什么
  • 商业汇票到期无法兑现
  • 应收账款折率
  • 物流公司怎么做利润高
  • 会计科目中英文对照表下载
  • 如何恢复数据库数据
  • sql删除查询结果
  • sql服务在哪
  • windowsxp的快捷键
  • Ubuntu安装ssh
  • 如何修复hosts文件
  • WinXp x64sp企业订户最新完整纯净版安装指南
  • win8怎么系统重装系统
  • win8自启动在哪儿设置
  • linux 防火墙原理
  • 卸载安装软件
  • linux shell语句
  • vs提示图标的含义
  • linux监控网络请求
  • cd跳转不到目录
  • jquery的children方法
  • jquery隐藏和显示div
  • js方法不执行
  • 怎么申请冬季取暖补贴
  • 变更税务登记后多长时间生效
  • 工会经费上缴地方工会15%的规定
  • 西安代驾平台有哪些
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设