SockJS实践:即时通信关键点

2024-04-01 05:18

本文主要是介绍SockJS实践:即时通信关键点,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

如果说之前的 Socket.IO打造基础聊天室 让我明白了聊天室的原理,知道了如何实现群聊(广播)和私聊(单播)等,那么对于 SockJS 的实践让我更加了解了websocket,因为 Sock.IO 是自己封装的接口,而 SockJS 则使用了跟 websocket 几乎相同的 API。

01 SockJS简介

  • 与 Socket.io 不同,在传输方式的选择方面,SockJS 会优先采用 websocket,然后再自动降级;
  • 其 API 几乎与 websocket API 的使用方式相同;
  • 兼容跨浏览器,支持跨域。

02 即时通信关键点

(1)心跳检测(业务层面)

(ws自身有心跳,但是如果有一些业务层面的需求,就需要自己实现心跳)

ws建立成功时便进行 心跳请求(每隔一段时间发送一个 PING),同时初始化 超时重连。如果在达到心跳规定次数后仍没有返回 PONG,则判定心跳超时,前端主动关闭ws,触发 ws重连

如果期间收到了 PONG,则重新初始化超时重连。

【注意】:ws重连的时候,要清空之前的心跳定时器。

(2)关闭连接的3种情况:

  • 心跳超时(连接层不断)的情况,则前端可主动关闭 ws;
  • 连接未建立成功(如TCP连接断掉),ws 自动关闭;
  • 服务端关闭(如多端剔除),这是要防止前端进行重连。

正常关闭(如心跳超时)

连接失败(如TCP层没有连接成功)

【注意】:锁屏情况下,js 会停止工作,这时,ws 会自动关闭,当屏幕唤醒时,通过触发 onclose 事件,ws 又会进行重连。在某些特殊业务场景下,需要注意下这种情况。

(3)websocket 自动重连

无论是前端主动关闭 ws,还是ws自动关闭,都会触发 onclose 事件,可在其中进行重连。如果达到了重连次数或者后端返回了不可进行重连的标志码,则不进行重连。

【实现思路】:

var CONNECT_COUNT = 3;
var sockjs;
var sockjs_url = '/chat/sjs/';
var isClose = false;
var connectCount = 1;new_conn = function() {    sockjs = new SockJS(sockjs_url);sockjs.onopen = function() {connectCount = 1;   // 重置重连次数this.checkHeartBeat();  // 心跳检测}sockjs.onmessage = function(e) {var data = JSON.parse(e.data);// handleMessage(data);};sockjs.onclose = function(e) {// 已经关闭的情况,不重连if (isClose) { return;}// 小于重连次数if (connectCount < CONNECT_COUNT) {setTimeout(function() {new_conn();}, (Math.random() * 3 + 1 )* 1000);   } else {isClose = true;}};
}

(4)sockJS session_id:可用于多端剔除

url格式类似于:/resource/<server_number>/<session_id>/transport

请求URL

每个 sockJS 都有 session_id,可通过它来判断是否同一个用户建立了2个ws,如多端登录的情况下,可用于进行多端剔除。

var socket = new SockJS('/mqClient');
stompClient = Stomp.over(socket);
stompClient.connect({}, function(frame) {console.log(socket._transport.url); //it contains ws://localhost:8080/mqClient/039/byxby3jv/websocket//sessionId is byxby3jv});

The SockJS constructor has an option parameter and there you can pass a custom session id generator as a function:

let sessionId = utils.random_string(8);
let socket = new SockJS('/socket', [], {sessionId: () => {return sessionId}});

 

03 sockJS readyState(暂时没用到。。)

【sockjs-client 部分源码】:

SockJS.CONNECTING = 0;
SockJS.OPEN = 1;
SockJS.CLOSING = 2;
SockJS.CLOSED = 3;
SockJS.prototype.close = function(code, reason) {// Step 1if (code && !userSetCode(code)) {throw new Error('InvalidAccessError: Invalid code');}// Step 2.4 states the max is 123 bytes, but we are just checking lengthif (reason && reason.length > 123) {throw new SyntaxError('reason argument has an invalid length');}// Step 3.1if (this.readyState === SockJS.CLOSING || this.readyState === SockJS.CLOSED) {return;}// TODO look at docs to determine how to set thisvar wasClean = true;this._close(code || 1000, reason || 'Normal closure', wasClean);
};

参考

  • 学习WebSocket协议—从顶层到底层的实现原理(修订版)
  • websocket RFC - EN
  • websocket RFC(翻译)
  • sockjs chat room
  • What happens if sockJS gets disconnected?

 

这篇关于SockJS实践:即时通信关键点的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/866289

相关文章

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

【STM32】SPI通信-软件与硬件读写SPI

SPI通信-软件与硬件读写SPI 软件SPI一、SPI通信协议1、SPI通信2、硬件电路3、移位示意图4、SPI时序基本单元(1)开始通信和结束通信(2)模式0---用的最多(3)模式1(4)模式2(5)模式3 5、SPI时序(1)写使能(2)指定地址写(3)指定地址读 二、W25Q64模块介绍1、W25Q64简介2、硬件电路3、W25Q64框图4、Flash操作注意事项软件SPI读写W2

vue2 组件通信

props + emits props:用于接收父组件传递给子组件的数据。可以定义期望从父组件接收的数据结构和类型。‘子组件不可更改该数据’emits:用于定义组件可以向父组件发出的事件。这允许父组件监听子组件的事件并作出响应。(比如数据更新) props检查属性 属性名类型描述默认值typeFunction指定 prop 应该是什么类型,如 String, Number, Boolean,

Prometheus与Grafana在DevOps中的应用与最佳实践

Prometheus 与 Grafana 在 DevOps 中的应用与最佳实践 随着 DevOps 文化和实践的普及,监控和可视化工具已成为 DevOps 工具链中不可或缺的部分。Prometheus 和 Grafana 是其中最受欢迎的开源监控解决方案之一,它们的结合能够为系统和应用程序提供全面的监控、告警和可视化展示。本篇文章将详细探讨 Prometheus 和 Grafana 在 DevO

springboot整合swagger2之最佳实践

来源:https://blog.lqdev.cn/2018/07/21/springboot/chapter-ten/ Swagger是一款RESTful接口的文档在线自动生成、功能测试功能框架。 一个规范和完整的框架,用于生成、描述、调用和可视化RESTful风格的Web服务,加上swagger-ui,可以有很好的呈现。 SpringBoot集成 pom <!--swagge

linux中使用rust语言在不同进程之间通信

第一种:使用mmap映射相同文件 fn main() {let pid = std::process::id();println!(

vue2实践:el-table实现由用户自己控制行数的动态表格

需求 项目中需要提供一个动态表单,如图: 当我点击添加时,便添加一行;点击右边的删除时,便删除这一行。 至少要有一行数据,但是没有上限。 思路 这种每一行的数据固定,但是不定行数的,很容易想到使用el-table来实现,它可以循环读取:data所绑定的数组,来生成行数据,不同的是: 1、table里面的每一个cell,需要放置一个input来支持用户编辑。 2、最后一列放置两个b

【HarmonyOS】-TaskPool和Worker的对比实践

ArkTS提供了TaskPool与Worker两种多线程并发方案,下面我们将从其工作原理、使用效果对比两种方案的差异,进而选择适用于ArkTS图片编辑场景的并发方案。 TaskPool与Worker工作原理 TaskPool与Worker两种多线程并发能力均是基于 Actor并发模型实现的。Worker主、子线程通过收发消息进行通信;TaskPool基于Worker做了更多场景化的功能封装,例

vue2实践:第一个非正规的自定义组件-动态表单对话框

前言 vue一个很重要的概念就是组件,作为一个没有经历过前几代前端开发的我来说,不太能理解它所带来的“进步”,但是,将它与后端c++、java类比,我感觉,组件就像是这些语言中的类和对象的概念,通过封装好的组件(类),可以通过挂载的方式,非常方便的调用其提供的功能,而不必重新写一遍实现逻辑。 我们常用的element UI就是由饿了么所提供的组件库,但是在项目开发中,我们可能还需要额外地定义一