WebSocket实现消息实时推送

文章目录

    • websocket介绍
      • 特点
      • 工作原理
    • 用websocket实现实时推送
      • 引入依赖
      • WebSocket 函数定义
      • 变量声明
      • 初始化 WebSocket 连接
      • WebSocket 连接的初始化和事件处理
      • 连接打开事件
      • 接收消息处理
      • 连接关闭和重连机制
      • 心跳机制
      • 使用 WebSocket
      • 代码完整显示

websocket介绍

WebSocket 是一种网络通信协议,旨在实现客户端和服务器之间的双向通信。它允许在单个 TCP 连接上进行全双工(即同时进行发送和接收)通信。WebSocket 特别适用于需要实时更新的应用,比如在线游戏、聊天应用、实时数据流等。

特点

双向通信:与传统的 HTTP 请求-响应模型不同,WebSocket 允许客户端和服务器同时发送和接收数据,这意味着一方可以主动向另一方发送消息,而不需要等待请求。

持久连接:WebSocket 建立的连接是持久的,客户端和服务器在一次连接后可以持续交换消息,而不需要频繁建立和关闭连接,从而减少了网络延迟和开销。

低延迟:由于使用了持久连接,WebSocket 可以减少消息传输中的延迟,使实时应用的响应速度更快。

轻量级:WebSocket 协议在数据传输中相对轻量,不需要像 HTTP 那样包含大量的头信息,数据包开销更小。

工作原理

握手:首先,客户端通过发送 HTTP 请求向服务器发起 WebSocket 连接。请求中包含一些特定的头信息,表明希望升级到 WebSocket 协议。

建立连接:服务器收到请求后,如果支持 WebSocket,将返回一个响应,确认升级连接。此时,HTTP 连接转变为 WebSocket 连接。

数据传输:连接建立后,双方可以自由地发送和接收消息。消息格式可以是文本(如 JSON)或二进制数据。

关闭连接:一方可以发送关闭帧,另一方收到后也会关闭连接,整个通信过程结束。

用websocket实现实时推送

这个封装提供了一个基础的 WebSocket 功能,可以支持实时消息推送。通过增加事件监听的管理、错误处理、灵活的心跳机制等功能,可以使这个封装更加健壮和灵活。

引入依赖

import { ElMessage, getCache } from "@/utils";

ElMessage: 用于显示消息提示。
getCache: 用于获取缓存数据,这里用来获取用户ID。

WebSocket 函数定义

function webSocket(params: string) {...return {onMessageFns,init,};
}

webSocket 函数接收一个参数 params(通常是用户ID),用于建立特定的 WebSocket 连接。

变量声明

  let urlParams: string = params;const isReconnect = ref(true);let reconnection: any;let ws: WebSocket | null = null;let websocketConnectedCount = 0;let serverTimeoutObj: any = null;const hearbeatInterval = 300000; // 心跳间隔

is_reconnect: 用于标识是否可以重连。
ws: 存储 WebSocket 实例。
websocketConnectdCount : 记录连接失败次数。
serverTimeoutObj : 用于管理心跳检测的定时器。

初始化 WebSocket 连接

const init = () => {if (!("WebSocket" in window)) {ElMessage({message: "抱歉,浏览器不支持Websocket!",type: "warning",duration: 1000,});return;}try {initWebSocket();} catch (e) {console.log("尝试创建连接失败");reConnect();}
};

首先检查浏览器是否支持 WebSocket。如果支持,则尝试初始化连接;如果失败,则调用 reConnect 进行重连。

WebSocket 连接的初始化和事件处理

 function initWebSocket() {const baseUrl = import.meta.env.VITE_BaseUrl?.slice(7);const url = `ws://${baseUrl}/websocket/${urlParams}`;ws = new WebSocket(url);ws.onopen = (e: Event) => {websocketOpen(e);};ws.onmessage = (e: MessageEvent) => {websocketOnMessage(e);};ws.onerror = () => {console.log("WebSocket连接发生错误");isReconnect.value = false;websocketConnectedCount++;if (websocketConnectedCount <= 5) {reConnect();}};ws.onclose = (e: CloseEvent) => {websocketClose(e);};}

创建 WebSocket 实例,并设置各类事件处理函数(打开、接收消息、错误、关闭)。

连接打开事件

function websocketOpen(e: Event) {console.log("连接成功");reset();start();const data = { sendType: "HEALTH" };ws?.send(JSON.stringify(data));}
}

连接成功时,重置心跳并发送健康检查消息。

接收消息处理

const onMessageFns = new Set<(e: MessageEvent) => void>();function websocketOnMessage(e: MessageEvent) {onMessageFns.forEach((callback) => callback(e));reset();start();return e.data;}

接收到消息时,执行所有注册的回调函数,并重置心跳。

连接关闭和重连机制

function websocketclose(e: any) {console.log(e);is_reconnect.value = false;console.log("connection closed (" + e.code + ")");
}let reConnect = () => {console.log("尝试重新连接");if (is_reconnect) return; // 如果已经连上就不再重连reconnection && clearTimeout(reconnection);reconnection = setTimeout(function () {init();}, 5000);
};

连接关闭时设置标识,并在指定时间后尝试重连。

心跳机制

 const reset = () => {clearTimeout(serverTimeoutObj);};const start = () => {serverTimeoutObj = setInterval(() => {if (ws?.readyState === WebSocket.OPEN) {console.log("连接状态,发送消息保持连接");const data = { sendType: "HEALTH" };ws?.send(JSON.stringify(data));reset();} else {console.log("断开连接, 尝试重连");webSocket(urlParams);}}, hearbeatInterval);};

定期发送健康检查消息,保持连接活跃。

使用 WebSocket

import webSocket from "@/utils/websocket";const userId = getCache("userId");
const ws = webSocket(userId)!;onMounted(async () => {const addMessage = () => {ws.onMessageFns.add((value: MessageEvent) => {try {if (value.data !== "来自后台的反馈:连接成功" && value.data !== "SUCCESS") {const parsedData = JSON.parse(value.data);console.log("获取到的信息", parsedData);}} catch (error) {console.error("消息解析错误:", error);}});};addMessage();
});

在组件挂载时,获取用户ID并创建 WebSocket 实例。添加消息接收处理,过滤特定消息并处理 JSON 数据。

代码完整显示

import { ElMessage, getCache } from "@/utils";function webSocket(params: string) {let urlParams: string = params;const isReconnect = ref(true);let reconnection: any;let ws: WebSocket | null = null;let websocketConnectedCount = 0;let serverTimeoutObj: any = null;const hearbeatInterval = 300000; // 心跳间隔const init = () => {if (!("WebSocket" in window)) {ElMessage({message: "抱歉,浏览器不支持WebSocket!",type: "warning",duration: 1000,});return;}try {initWebSocket();} catch (e) {console.log("尝试创建连接失败");reConnect();}};function initWebSocket() {const baseUrl = import.meta.env.VITE_BaseUrl?.slice(7);const url = `ws://${baseUrl}/websocket/${urlParams}`;ws = new WebSocket(url);ws.onopen = (e: Event) => {websocketOpen(e);};ws.onmessage = (e: MessageEvent) => {websocketOnMessage(e);};ws.onerror = () => {console.log("WebSocket连接发生错误");isReconnect.value = false;websocketConnectedCount++;if (websocketConnectedCount <= 5) {reConnect();}};ws.onclose = (e: CloseEvent) => {websocketClose(e);};}function websocketOpen(e: Event) {console.log("连接成功");reset();start();const data = { sendType: "HEALTH" };ws?.send(JSON.stringify(data));}const onMessageFns = new Set<(e: MessageEvent) => void>();function websocketOnMessage(e: MessageEvent) {onMessageFns.forEach((callback) => callback(e));reset();start();return e.data;}function websocketClose(e: CloseEvent) {console.log("connection closed (" + e.code + ")");isReconnect.value = false;}const reConnect = () => {console.log("尝试重新连接");if (isReconnect.value) return; // 如果已经连上就不再重连reconnection && clearTimeout(reconnection);reconnection = setTimeout(init, 5000);};const reset = () => {clearTimeout(serverTimeoutObj);};const start = () => {serverTimeoutObj = setInterval(() => {if (ws?.readyState === WebSocket.OPEN) {console.log("连接状态,发送消息保持连接");const data = { sendType: "HEALTH" };ws?.send(JSON.stringify(data));reset();} else {console.log("断开连接, 尝试重连");webSocket(urlParams);}}, hearbeatInterval);};return {onMessageFns,init,};
}// 使用 WebSocket
import webSocket from "@/utils/websocket";const userId = getCache("userId");
const ws = webSocket(userId)!;onMounted(async () => {const addMessage = () => {ws.onMessageFns.add((value: MessageEvent) => {try {if (value.data !== "来自后台的反馈:连接成功" && value.data !== "SUCCESS") {const parsedData = JSON.parse(value.data);console.log("获取到的信息", parsedData);}} catch (error) {console.error("消息解析错误:", error);}});};addMessage();
});

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

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

相关文章

C++入门基础知识134—【关于C 库函数 - gmtime()】

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///C爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C 库函数 - gmtime()的相关内容&#xf…

ERP学习笔记-预处理eeglab

第一步&#xff1a;数据格式转化 import data&#xff1a;读取收集到的原始数据文件.vhdr格式 读取后的样子&#xff1a; 将数据保存为.set文件 第二步&#xff1a;通道定位 读取.set文件 Channel locations部分为unknown&#xff0c;表明通道的坐标未知 增加默认的设置 Chan…

查缺补漏----用户上网过程(HTTP,DNS与ARP)

&#xff08;1&#xff09;HTTP 来自湖科大计算机网络微课堂&#xff1a; ① HTTP/1.0采用非持续连接方式。在该方式下&#xff0c;每次浏览器要请求一个文件都要与服务器建立TCP连接当收到响应后就立即关闭连接。 每请求一个文档就要有两倍的RTT的开销。若一个网页上有很多引…

谷歌推出全新AI生成游戏玩法 —— 无限生成角色生活模拟游戏“Unbounded”

随着人工智能技术的飞速发展,游戏行业正迎来前所未有的创新。近日,谷歌宣布了一款名为“Unbounded”的新型游戏,这是一款基于生成式AI技术的角色生命模拟游戏,它将为玩家带来前所未有的开放性和互动性体验。 项目概览 项目名称:Unbounded类型:生成式无限游戏(Generati…

论文阅读:DynamicDet: A Unified Dynamic Architecture for Object Detection

论文地址&#xff1a;[2304.05552] DynamicDet: A Unified Dynamic Architecture for Object Detection 代码地址&#xff1a;GitHub - VDIGPKU/DynamicDet: [CVPR 2023] DynamicDet: A Unified Dynamic Architecture for Object Detection 概要 本文提出了一种名为 DynamicD…

关于在GitLab的CI/CD中用docker buildx本地化多架构打包dotnet应用的问题

关于在GitLab的CI/CD中用docker buildx本地化多架构打包dotnet应用的问题 这是一个DevOps综合性问题docker buildx多架构打包.NET应用的问题用QEMU模拟多架构环境打包 这是一个DevOps综合性问题 网络上的方案都是细分的领域&#xff0c;未见一个集成了GitLabdockerdotnet的多架…

翻译工具开发技术笔记:《老挝语翻译通》app支持语音识别翻译功能,怎么提高语音识别的准确度呢?

《老挝语翻译通》app是一款专为老挝语翻译设计的免费工具&#xff0c;支持文本翻译、老挝文OCR文字识别提取、文字转语音。这款工具以其技术优势和用户友好的界面&#xff0c;为用户提供了便捷的老挝语翻译体验。 技术特点 文本翻译&#xff1a;支持双语输入&#xff0c;提供精…

qt QListView详解

1、概述 QListView 是 Qt 框架中的一个视图类&#xff0c;用于展示模型中的数据。它基于 QAbstractItemView&#xff0c;支持多种视图模式&#xff0c;如列表视图&#xff08;List View&#xff09;、图标视图&#xff08;Icon View&#xff09;等。QListView 是模型/视图框架…

初识C++(上) -- C++的关键字、命名空间、缺省参数以及函数的重载

目录 一、C的关键字&#xff08;C98&#xff09; 二、命名空间 1、命名冲突 2、命名空间 2.1 命名空间的定义 (1). 命名空间定义的例子以及命名空间的嵌套&#xff1a; (2). 同一个工程中允许存在多个相同名称的命名空间,编译器最后会合成同一个命名空间中&#xff1a; 2…

MySQL_客户端工具建库.

前言&#xff1a; 通过前面的学习我们已经了解到什么是数据库&#xff0c;以及数据库是如何安装的&#xff0c;相信大家都已将数据库安装好了&#xff0c;让我们接下来开始新的学习吧&#xff01;&#xff01;&#xff01; 1.MySQL客户端工具 1. MySQL Workbench MySQL :: D…

突破1200°C高温性能极限!北京科技大学用机器学习合成24种耐火高熵合金,室温延展性极佳

在工程应用中&#xff0c;如燃气轮机、核反应堆和航空推进系统&#xff0c;对具备优异高温机械性能的金属合金需求十分旺盛。由于材料熔点的固有限制&#xff0c;传统镍基 (Ni) 高温合金的耐温能力已接近极限。为满足开发高温结构材料的需求&#xff0c;耐火高熵合金 (RHEAs) 于…

leetcode21:合并两个有序列表

将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。 示例 1&#xff1a; 输入&#xff1a;l1 [1,2,4], l2 [1,3,4] 输出&#xff1a;[1,1,2,3,4,4]示例 2&#xff1a; 输入&#xff1a;l1 [], l2 [] 输出&#xff1a;[]示…

开源模型应用落地-glm模型小试-glm-4-9b-chat-vLLM集成(四)

一、前言 GLM-4是智谱AI团队于2024年1月16日发布的基座大模型&#xff0c;旨在自动理解和规划用户的复杂指令&#xff0c;并能调用网页浏览器。其功能包括数据分析、图表创建、PPT生成等&#xff0c;支持128K的上下文窗口&#xff0c;使其在长文本处理和精度召回方面表现优异&a…

K8S篇(基本介绍)

目录 一、什么是Kubernetes&#xff1f; 二、Kubernetes管理员认证&#xff08;CKA&#xff09; 1. 简介 2. 考试难易程度 3. 考试时长 4. 多少分及格 5. 考试费用 三、Kubernetes整体架构 Master Nodes 四、Kubernetes架构及和核心组件 五、Kubernetes各个组件及功…

关于路由笔记

路由 定义&#xff1a; 在计算机网络中&#xff0c;路由是将数据包从源节点传输到目标节点的过程。这个过程涉及到网络中的多个设备&#xff0c;如路由器、交换机等&#xff0c;其中路由器起着关键的决策作用。 工作原理示例&#xff1a; 假设你在一个公司的局域网内&#…

人工智能之人脸识别(人脸采集人脸识别)

文章目录 前言PySimpleGUI 库1-布局和窗口 前言 例如&#xff1a;随着人工智能的不断发展&#xff0c;本文主要介绍关于人工智能中GUI和PyMysql相应用。 本文采用代码&#xff0b;逻辑思路分析的方式有助于理解代码。 PySimpleGUI 库 PySimpleGUI 是一个用于简化 GUI 编程的…

如何找到养生生活视频素材?推荐几个优秀网站

今天&#xff0c;我们来聊一个实用的话题&#xff0c;那就是如何找到优质的养生视频素材。作为自媒体创作者&#xff0c;高质量的视频素材对内容制作至关重要。不论你是刚入行的新手&#xff0c;还是已经积累了一定粉丝的大V&#xff0c;找到合适的养生视频素材都能帮助你更好地…

旋转对称性,旋转矩阵的特征矢量也是T3矩阵的特征矢量

旋转对称性要求T3矩阵&#xff0c;在旋转后&#xff0c;特征矢量没发生改变&#xff0c;特征值大小也没变&#xff0c;即T3矩阵没有改变

美畅物联丨物联网通信新纪元:Cat.1与5G RedCap的差异化应用

​ 在物联网&#xff08;IoT&#xff09;迅猛发展的时代&#xff0c;通信标准对物联网设备的连接性、性能和适用性有着极为关键的作用。小编在《美畅物联丨Cat.1与NB-IoT&#xff1a;物联网设备的通信标准对比》中提到Cat.1与NB-IoT的对比区别&#xff0c;后来就有小伙伴问&…

OpenCV视觉分析之目标跟踪(12)找到局部的最大值函数meanShift()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在反向投影图像上找到一个对象。 meanShift 是一种用于图像处理和计算机视觉领域的算法&#xff0c;特别适用于目标跟踪、图像分割等任务。该算…