WebSocket 断网重连、心跳检测功能封装

文章目录

  • 简介
    • 特点
    • 优缺点
    • 使用场景
  • 用法
  • 封装
    • 断网重连
    • 心跳检测
  • 注意

简介

WebSocket是一种用于在Web浏览器和服务器之间进行双向通信的协议。它提供了一种在单个TCP连接上进行持久化的全双工通信能力。WebSocket协议通过在HTTP握手阶段升级到WebSocket连接,从而允许双方之间建立持久连接。一旦WebSocket连接建立,服务器和客户端就可以通过发送消息来进行实时通信。这种双向通信机制。

Websocket 协议与 HTTP 协议没有关系,它是一个建立在 TCP 协议上的全新协议,为了兼容 HTTP 握手规范,在握手阶段依然使用 HTTP 协议,握手完成之后,数据通过 TCP 通道进行传输。

Websoket 数据传输是通过 frame 形式,一个消息可以分成几个片段传输。这样大数据可以分成一些小片段进行传输,不用考虑由于数据量大导致标志位不够的情况。也可以边生成数据边传递消息,提高传输效率。

特点

  • 双向通信:服务器和客户端可以通过发送消息进行实时双向通信。

  • 持久连接:WebSocket连接是持久的,不需要在每次通信时重新建立连接。

  • 低开销:与传统的HTTP请求相比,WebSocket通信的开销较低,因为不需要频繁地建立和关闭连接。

  • 低延迟:由于协议是全双工的,所以服务器可以随时主动给客户端下发数据。相对于HTTP请求需要等待客户端发起请求服务端才能响应,延迟明显更少。

  • 支持跨域:WebSocket协议支持跨域通信,可以在不同域名或端口之间进行通信。

  • 减少数据传输:由于WebSocket是基于消息的,而不是基于请求/响应的,因此可以减少不必要的数据传输,从而提高传输效率。

优缺点

优点:
双向通信。客户端和服务端双方 都可以主动发起通讯。 没有同源限制。客户端可以与任意服务端通信,不存在跨域问题。 数据量轻。第一次连接时需要携带请求头,后面数据通信都不需要带请求头,减少了请求头的负荷。 传输效率高。因为只需要一次连接,所以数据传输效率高。

缺点:
长连接需要后端处理业务的代码更稳定,推送消息相对复杂; 兼容性,WebSocket 只支持 IE10 及其以上版本。 服务器长期维护长连接需要一定的成本,各个浏览器支持程度不一; 【需要后端代码稳定,受网络限制大,兼容性差,维护成本高,生态圈小】

使用场景

  1. 协同编辑

    • 场景描述:WebSocket可用于实现多人协同编辑,如在线文档协作、团队代码编辑等。
    • 实际应用:多个用户可以同时编辑同一个文档或代码文件,他们的编辑结果会实时地同步到其他用户的界面上。
      .
  2. 实时监控

    • 场景描述:WebSocket适用于实时监控系统,如监控设备的运行状态、实时监测交通流量等。
    • 实际应用:服务器可以实时地将监控数据推送给客户端,客户端可以及时地显示最新的监控信息。
      .
  3. 实时聊天

    • 场景描述:WebSocket是即时通讯的理想选择,如在线聊天室、多人游戏等。
    • 实际应用:客户端和服务器可以实时地发送和接收消息,无需频繁地发起HTTP请求。
      .
  4. 实时数据更新

    • 场景描述:WebSocket能够实时推送数据更新,如实时股票行情、实时天气预报等。
    • 实际应用:服务器可以实时地将最新的数据推送给客户端,客户端无需主动发起请求。
      .
  5. 游戏开发

    • 场景描述:WebSocket在游戏开发中具有重要作用,特别是在多人在线游戏中。
    • 实际应用:
      • 多人游戏协同:允许多个客户端同时连接到服务器,使多人协同游戏变得容易。
      • 实时聊天:游戏内的实时聊天变得非常容易实现。
      • 服务器推送:服务器可以主动推送消息给客户端,降低了服务器和网络的负担。
      • 实时排行榜和统计:游戏服务器可以实时更新排行榜和统计信息。
      • 游戏状态同步:通过建立持久的WebSocket连接,游戏服务器可以实时广播游戏状态的更新。

用法

在JavaScript中使用WebSocket相当直观。以下是一个基本的WebSocket客户端使用示例,它演示了如何连接到WebSocket服务器、发送消息、接收消息以及处理连接关闭。

首先,确保你的WebSocket服务器已经启动并在监听某个端口(比如ws://localhost:8080)。

// 创建一个新的WebSocket实例,连接到指定的URL  
var socket = new WebSocket('ws://localhost:8080');  // 连接打开事件  
socket.onopen = function(event) {  console.log("WebSocket连接已打开");  // 连接打开后,可以发送消息   socket.send('Hello Server!');  
};  // 接收消息事件  
socket.onmessage = function(event) {  console.log("收到来自服务器的消息: " + event.data);  // 处理接收到的消息  // 可以将event.data解析为JSON或其他格式  // let data = JSON.parse(event.data);  
};  // 错误事件  
socket.onerror = function(error) {  console.error('WebSocket连接发生错误:', error);  // 在这里处理错误情况  
};  // 连接关闭事件  
socket.onclose = function(event) {  if (event.wasClean) {  console.log("WebSocket连接已正常关闭");  } else {  console.log("WebSocket连接发生异常关闭");  }  // 可以在这里尝试重新连接  
};  // 发送消息的函数  
function sendMessage(message) {  if (socket.readyState === WebSocket.OPEN) {  socket.send(message);  } else {  console.log('WebSocket连接未打开,消息未发送: ' + message);  }  
}  // 你可以在其他地方调用sendMessage函数来发送消息  
// sendMessage('这是一条新的消息');  // 当你不再需要WebSocket连接时,可以手动关闭它  
// socket.close();
  • 创建了一个新的WebSocket对象,并指定了要连接的WebSocket服务器URL

  • 为WebSocket对象添加了几个事件监听器,以处理连接建立、接收到消息、发生错误和连接关闭等事件:

    • onopen:在连接建立时触发,你可以在这个事件处理函数中发送初始消息

    • onmessage:在接收到消息(来自服务器)时触发,你可以在这个事件处理函数中处理接收到的消息

    • onerror:在发生错误时触发

    • onclose:在连接关闭时触发

  • sendMessage函数是一个简单的封装,用于在WebSocket连接打开时发送消息。如果连接未打开,它会打印一条消息到控制台。

  • 最后,调用 socket.close() 来手动关闭 WebSocket 连接。但通常,当不再需要 WebSocket 连接时,或者当服务器关闭连接时,连接会自动关闭。


封装

封装一个支持断网重连心跳检测功能,并且兼容原生WebSocket写法的JavaScript WebSocket类

断网重连

WebSocket 断网重连(Reconnect after Network Disconnection)是指在 WebSocket 连接因为网络问题(如网络不稳定、临时断网、服务器宕机等)而断开后,客户端能够自动检测到连接已断开,并在网络恢复后尝试重新建立与服务器的 WebSocket 连接的过程。

在网络通信中,由于各种不可控因素,WebSocket 连接可能会意外断开。为了确保服务的连续性和可用性,很多 WebSocket 客户端库或框架都会提供断网重连的功能。

  1. 连接状态监听:客户端需要监听 WebSocket 的 onclose 事件,该事件会在连接关闭时被触发。一旦接收到 onclose 事件,客户端就知道连接已经断开。

  2. 重连策略:在连接断开后,客户端会根据预定义的重连策略来决定是否尝试重新连接。重连策略可以包括重连间隔、重连次数限制等。例如,客户端可能会等待一段时间后再次尝试连接,如果连接仍然失败,它会继续等待更长的时间再次尝试,直到达到最大重连次数或用户干预。

  3. 重连实现:在决定重连后,客户端会重新调用 WebSocket 的构造函数或相关方法,以尝试与服务器建立新的 WebSocket 连接。如果连接成功,客户端会恢复正常的通信。

  4. 心跳检测:为了更准确地检测连接状态,很多 WebSocket 客户端还会实现心跳检测机制。客户端定期向服务器发送心跳消息,如果服务器在规定的时间内没有响应,客户端就认为连接已经断开,并开始执行重连逻辑。

  5. 日志和通知:在重连过程中,客户端可能会记录日志以便后续分析,并在需要时向用户或开发者发送通知。

心跳检测

WebSocket 心跳(Heartbeat)是指为了在 WebSocket 连接中检测连接的活跃性和可用性而定期发送的简短消息。WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,允许服务器主动向客户端推送信息,客户端也可以主动向服务器发送信息。

由于网络环境的复杂性,如网络不稳定、防火墙或代理服务器配置不当等原因,WebSocket 连接有时可能会“假死”,即连接仍然处于打开状态(readyState 为 OPEN),但实际上数据已经无法传输。在这种情况下,如果没有任何数据在连接上传输,双方都无法得知连接是否已经失效。

为了解决这个问题,可以定期发送心跳消息来检测连接的活跃性。心跳消息通常是一个简短的数据包,例如一个简单的字符串或数字。客户端和服务器都可以发送心跳消息,但通常是由客户端发送,因为服务器可以更容易地检测和管理多个连接。

当接收到心跳消息时,接收方会重置其心跳定时器,并知道连接仍然是活跃的。如果在指定的时间间隔内没有收到心跳消息,接收方可以认为连接已经失效,并采取相应的措施,如关闭连接、尝试重新连接或通知用户。

  1. 发送频率:心跳消息的发送频率应该根据具体的应用场景和网络环境来确定。过于频繁的心跳消息可能会增加网络负担,而发送间隔过长则可能无法及时发现连接问题。

  2. 消息内容:心跳消息的内容应该简短,以减少网络带宽的占用。通常,一个简单的字符串或数字就足够了。

  3. 处理接收到的消息:当接收到心跳消息时,接收方应该重置其心跳定时器,并继续等待下一个心跳消息。如果接收到非心跳消息,则应该根据应用的逻辑来处理。

  4. 重连机制:如果心跳检测发现连接已经失效,接收方应该尝试重新建立连接。重连的间隔和次数可以根据需要来配置。

// ReliableWebSocket 类,封装了原生 WebSocket,支持断网重连和自动心跳功能  
class ReliableWebSocket {  // 构造函数,接收 WebSocket 服务器的 URL 和可选的配置选项  constructor(url, options = {}) {  this.url = url;                               // WebSocket 服务器的 URL  this.options = options;                       // 可选配置选项  // 重连间隔时间,默认为 5000 毫秒(5 秒)  this.reconnectInterval = options.reconnectInterval || 5000;  // 心跳间隔时间,默认为 30000 毫秒(30 秒)  this.heartbeatInterval = options.heartbeatInterval || 30000;  // 心跳消息内容,默认为 'ping'  this.heartbeatMessage = options.heartbeatMessage || 'ping';  // WebSocket 实例  this.socket = null;  // 心跳定时器  this.heartbeatTimer = null;  // 初始化 WebSocket 连接  this.init();  }  // 初始化 WebSocket 连接  init() {  // 创建 WebSocket 实例  this.socket = new WebSocket(this.url);  // 当 WebSocket 连接打开时  this.socket.onopen = (event) => {  // 开始发送心跳消息  this.startHeartbeat();  console.log('WebSocket 连接已打开');  };  // 当接收到 WebSocket 消息时  this.socket.onmessage = (event) => {  // 重置心跳定时器  this.resetHeartbeat();  console.log('收到消息:', event.data);  };  // 当 WebSocket 连接关闭时  this.socket.onclose = (event) => {  // 停止发送心跳消息  this.stopHeartbeat();  console.log('WebSocket 连接已关闭', event);  // 尝试重新连接  this.reconnect();  };  // 当 WebSocket 连接发生错误时  this.socket.onerror = (error) => {  console.error('WebSocket 连接发生错误:', error);  };  }  // 开始发送心跳消息  startHeartbeat() {  // 设置定时器,按照指定的间隔发送心跳消息  this.heartbeatTimer = setInterval(() => {  if (this.socket.readyState === WebSocket.OPEN) {  this.socket.send(this.heartbeatMessage);  }  }, this.heartbeatInterval);  }  // 重置心跳定时器  resetHeartbeat() {  // 清除旧的心跳定时器并重新开始  clearInterval(this.heartbeatTimer);  this.startHeartbeat();  }  // 停止发送心跳消息  stopHeartbeat() {  // 清除心跳定时器  clearInterval(this.heartbeatTimer);  }  // 尝试重新连接 WebSocket  reconnect() {  // 设置定时器,按照指定的间隔尝试重新连接  let intervalId = setInterval(() => {  try {  // 尝试重新初始化 WebSocket 连接  this.init();  // 如果连接成功,则清除定时器  clearInterval(intervalId);  } catch (e) {  console.error('重连失败,稍后重试...', e);  }  }, this.reconnectInterval);  }  // 发送消息到 WebSocket 服务器  send(data) {  if (this.socket.readyState === WebSocket.OPEN) {  this.socket.send(data);  } else {  console.error('WebSocket 连接未打开,无法发送消息');  }  }  // 关闭 WebSocket 连接  close() {  if (this.socket) {  this.socket.close();  }  }  // ... 可以继续封装其他 WebSocket 原生方法,如添加事件监听器等  
}  // 使用示例  
const ws = new ReliableWebSocket('ws://your-websocket-server-url');  
ws.send('Hello, Server!');  // 如果需要监听事件,可以在 ReliableWebSocket 类中添加事件触发逻辑  
// 例如,使用 EventEmitter 或者发布订阅模式

注意

  • WebSocket连接可以使用安全的WebSocket协议(wss://)进行保护,它使用SSL/TLS添加了额外的加密层。这确保了在客户端和服务器之间传输的数据的机密性和完整性。

  • WebSocke t是一种基于TCP的协议,支持长连接。在实际使用中,需要注意及时维护长连接,避免因连接长时间不活跃而被网络设备断开。为了确保长连接的稳定性,可以定时发送心跳包,以保持连接的活跃状态。

  • 大多数现代Web浏览器都支持WebSocket协议,包括Chrome、Firefox、Safari和Edge。然而,需要考虑WebSocket在旧浏览器或支持有限的环境中的兼容性。在这种情况下,可以使用回退机制。

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

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

相关文章

100页2秒?我们为什么需要这样的文档解析速度

近期,TextIn通用文档解析完成最新一版产品迭代,将100页文档解析速度提升至最快2秒以内。 P50(百页) P90(百页) P95(百页) P99(百页) 平均(单页…

记某网关系统通用漏洞的挖掘

前言 本篇文章分享一下通用漏洞挖掘的过程,想要获得通用漏洞证书,首先要求是中危及中危以上的通用型漏洞且所属公司的注册资本大于5000万。挖掘一个漏洞其实不难,个人觉得是目标公司资产的搜集。访问CNVD平台发现某网关系统被师傅提交过任意…

陈文自媒体:人生的管道收入,你搭建了几条?

今天不讲行业的内容,今天说说一下人生的一些规划,可能有人说,现在社会变化这么快,谈啥规划,那不是笑话嘛? 其实我想说,提前规划比没有规划,效果完全不一样, 是的社会变化…

V神的傲慢与偏见

原创 | 刘教链 隔夜BTC(比特币)小幅回升至5日线67.7k附近。前日5.31教链内参“美核心通胀放缓,利好宽松周期落地”[链接]提到,以太坊创始人Vitalik Buterin(V神)新发表了一篇长文,主题是关于他“…

Java反射机制:深入探讨与实际应用

Java反射机制:深入探讨与实际应用 引言 反射机制是Java语言的重要特性之一,它允许程序在运行时检查和操作自身的结构。通过反射,开发者可以在运行时动态地获取类的详细信息,创建对象,调用方法,甚至修改字…

H6911 DC2.6-40V升压IC 升24V36V48V60V80V100V10A数转模无频闪LED芯片

H6911 DC2.6-40V升压IC是一款升压恒流LED恒流驱动器,具有多种特点,适用于多种的LED照明应用领域。以下是关于该产品的详细解释: 一、产品概述 H6911是一款专为LED照明设计的升压恒流驱动器。它能在2.6至40V的宽电压范围内稳定工作&#xff0c…

性能优化随笔(一)

在软件开发过程中,一般要先实现功能方面的需求,功能方面的需求开发完毕之后,往往会考虑性能方面的优化。在业务发展的初期,性能往往能满足使用的需求,这时性能优化不是必不可少的。随着业务的发展,软件复杂…

Window11开放端口

(1)打开控制面板,进入【控制面板\系统和安全\Windows Defender 防火墙】 (2)点击左侧菜单【高级设置】,进入防火墙设置页面 (3)根据需要选择【入站规则】或者【出站规则】&#xff…

粒子群算法Java实现

粒子群算法(Particle Swarm Optimization,PSO)是一种受到自然界群体行为启发的优化算法,由James Kennedy和Russell Eberhart于1995年提出。该算法模拟了鸟类或其他动物群体(如鱼群)的社会和集体行为&#x…

C++:特殊类设计和四种类型转换

一、特殊类设计 1.1 不能被拷贝的类 拷贝只会放生在两个场景中:拷贝构造函数以及赋值运算符重载,因此想要让一个类禁止拷贝,只需让该类不能调用拷贝构造函数以及赋值运算符重载即可。 C98: 1、将拷贝构造函数与赋值运算符重载只…

linux 内核映像差异介绍:vmlinux、zImage、zbImage、image、uImage等

一、背景 Linux内核是整个Linux操作系统的核心部分,它是一个负责与硬件直接交互的软件层,并且提供多种服务和接口,让用户程序能够方便地使用硬件资源。 当我们编译自定义内核时,可以将其生成为以下内核映像之一:vmli…

[每日一练]关于上升的温度查询

该题目来自于力扣: 197. 上升的温度 - 力扣(LeetCode) 题目要求: 表: Weather ------------------------ | Column Name | Type | ------------------------ | id | int | | recordDate | …

Java网络编程从入门到精通:深入探索与实践指南

Java网络编程从入门到精通:深入探索与实践指南 在数字化时代的浪潮中,Java网络编程已成为连接世界的桥梁。本文将从四个方面、五个方面、六个方面和七个方面,带你领略Java网络编程的魅力,助你实现从入门到精通的飞跃。 四个方面…

AP9185内置 MOS 管升压型恒流驱动芯片

概述 AP9185是一款高效率、高精度的升压型大功率LED灯恒流驱动器芯片。AP9185内置高精度误差放大器,固定关断时间控制电路,恒流驱动电路等,特别适合大功率、多个高亮度LED灯串的恒流驱动。AP9185通过调节外置的电流采样电阻,能控…

WordPress博客主题触屏版社区源码

下载地址:WordPress博客主题触屏版社区源码

【Java面试】八、MyBatis篇

文章目录 1、MyBatis执行流程2、MyBatis延迟加载使用3、MyBatis延迟加载的原理4、MyBatis的一级、二级缓存4.1 一级缓存4.2 二级缓存4.3 注意点 5、面试 1、MyBatis执行流程 从mybatis-config.xml读取配置(数据库连接信息,xml映射文件) 构建…

LeetCode 算法:无重复字符的最长子串c++

原题链接🔗:无重复字符的最长子串 难度:中等⭐️⭐️ 题目 给定一个字符串 s ,请你找出其中不含有重复字符的最长子串的长度。 示例 1: 输入: s “abcabcbb” 输出: 3 解释: 因为无重复字符的最长子串是 “abc”,所…

讯飞开发平台—语音听写模块使用

查看博文:讯飞开发平台—语音听写模块使用-CSDN博客

透视 static 和 extern 对函数的重大影响

目录 一、生命周期和作用域1、生命周期2、作用域 二、static 的影响1、static的作用2、static 修饰局部变量 三、extern 的魔力四、static 与 extern 的协同与冲突1、static修饰全局变量2、static修饰函数 在 C 语言的世界里, static 和 extern 这两个关键字在函数的…

[图解]企业应用架构模式2024新译本讲解07-表模块4

1 00:00:00,360 --> 00:00:07,030 这里面实际上就是通过一个方法,一个操作来封装了 2 00:00:08,790 --> 00:00:10,630 它不直接就操纵这里面 3 00:00:10,640 --> 00:00:12,070 不是直接把里面露出来 4 00:00:14,990 --> 00:00:20,430 产品ID进来&…