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.mzph.cn/web/58563.shtml

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

相关文章

视频制作与剪辑怎么学,零基础入门视频剪辑和制作

视频制作与剪辑是一门充满创意与挑战的艺术形式&#xff0c;对于零基础的学习者来说&#xff0c;没选对软件不了解剪辑步骤&#xff0c;入门可能会显得有些棘手。接下来&#xff0c;我们将一同探讨如何开启视频剪辑与制作之旅&#xff0c;让新手从零基础入门&#xff0c;逐步迈…

[Element] el-table修改滚动条上部分的背景色

[Element] el-table修改滚动条上部分的背景色 ::v-deep .el-table__cell .gutter {background: red;}

SAP ABAP开发学习——WDA 七 使用文本与消息

目录 从数据字典读取文本 使用OTR文本 从程序中调用OTR文本 消息分类 定义消息显示位置 text类消息的使用 T100 消息的使用 OTR消息实例 消息内容修改 从数据字典读取文本 使用OTR文本 可以自己创建OTR文本 从程序中调用OTR文本 消息分类 定义消息显示位置 text类消息的…

基于物联网设计的地下煤矿安全监测与预警

文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成 1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发 1.5 模块的技术详情介绍【1】NBIOT-BC26模块【2】MQ5传感器【4】DHT11传感器【5】红外热释电人体检…

golang分布式缓存项目 Day 1

注&#xff1a;该项目原作者&#xff1a;https://geektutu.com/post/geecache-day1.html。本文旨在记录本人做该项目时的一些疑惑解答以及部分的测试样例以便于本人复习。 LRU缓存淘汰策略 三种缓存淘汰策略 FIFO&#xff08;First In, First Out&#xff09;先进先出 原理&…

Pr 视频过渡:沉浸式视频 - VR 默比乌斯缩放

效果面板/视频过渡/沉浸式视频/VR 默比乌斯缩放 Video Transitions/Immersive Video/VR Mobius Zoom VR 默比乌斯缩放 VR Mobius Zoom用于 VR 视频中的缩放式场景切换&#xff0c;通过缩小或放大的渐变效果在两个场景之间平滑过渡。 自动 VR 属性 Auto VR Properties 默认勾选…

华为实时视频使用FLV播放RTSP流

import flvjs from ‘flv.js’; 安装flv <video style"width:100%;height:100%;" ref"videoHWRef" ></video>// src 华为rtsp流 rtsp://admin:Huaweivideo10.10.8.151:554/xxx/trackID1// url 需要后端提供视频源地址playVideo() {if (fl…

【华为机试题】光伏场地建设规划 [Python]

题目 代码 class Solution:def func(self, input_args, area_list):count 0for i in range(input_args[0] - input_args[2] 1):for j in range(input_args[1] - input_args[2] 1):count 1 if self.area_compute(area_list,i,j,input_args[2],input_args[3]) else 0print(c…

备考25年二建,最好这样选专业!

2025年的二建备考已经开始了&#xff0c;很多考生在纠结报考哪个专业&#xff0c;二级建造师各专业难度如何&#xff1f;哪个专业含金量更高&#xff1f; 今天就带大家了解一下这六大专业&#xff0c;一起来看~ ​建筑专业 考核方向&#xff1a;建筑工程技术要求、建筑工程专…

向量模型Jina Embedding: 从v1到v3论文笔记

文章目录 Jina Embedding: 从v1到v3Jina Embedding v1数据集准备训练过程 Jina Embedding v2预训练修改版BERT在文本对上微调在Hard Negatives上微调 Jina Embedding v2 双语言预训练修改版BERT在文本对上微调用多任务目标微调 Jina Embedding v3预训练在文本对上微调训练任务相…

「Mac畅玩鸿蒙与硬件28」UI互动应用篇5 - 滑动选择器实现

本篇将带你实现一个滑动选择器应用&#xff0c;用户可以通过滑动条选择不同的数值&#xff0c;并实时查看选定的值和提示。这是一个学习如何使用 Slider 组件、状态管理和动态文本更新的良好实践。 关键词 UI互动应用Slider 组件状态管理动态数值更新用户交互 一、功能说明 在…

全连接神经网络案例——手写数字识别

文章目录 1.我们导入需要的工具包2.数据加载3.数据处理4.模型构建5.模型编译6.模型训练7.模型测试8.模型保存 使⽤⼿写数字的MNIST数据集如上图所示&#xff0c;该数据集包含60,000个⽤于训练的样本和10,000个⽤于测试的样本&#xff0c;图像是固定⼤⼩(28x28像素)&#xff0c;…

2.ARM_ARM是什么

CPU工作原理 CPU与内存中的内容&#xff1a; 内存中存放了指令&#xff0c;每一个指令存放的地址不一样&#xff0c;所需的内存空间也不一样。 运算器能够进行算数运算和逻辑运算&#xff0c;这些运算在CPU中都是以运算电路的形式存在&#xff0c;一个运算功能对应一种运算电…

MetaGeneMark:宏转录组转录本基因预测

GeneMark™ download 下载 gunzip gm_key_64.gz tar -xvzf MetaGeneMark_linux_64.tar.gz #查看安装 (完整路径)/gmhmmp #解压文件里面这个比较重要 MetaGeneMark_linux_64/mgm/MetaGeneMark_v1.mod #复制gm_key文件到主路径 mv gm_key_64 .gm_key cp .gm_key /home/zhongpei…

腾讯轻量云服务器docker拉取不到镜像的问题:拉取超时

前言 也是尝试了各种解决方案之后&#xff0c;无果&#xff0c; 后来发现每个服务器提供商都有自己的镜像加速&#xff0c;且只给自家服务器使用&#xff0c;我用的腾讯云 教程 安装docker 直接上链接&#xff1a;云服务器 搭建 Docker-实践教程-文档中心-腾讯云 配置加速镜…

各家AI性格不同,怎样取长补短

你发现了么&#xff0c;每家的AI性格也有区别呢&#xff0c;有些AI比较啰嗦&#xff0c;有些AI回答简洁明了&#xff0c;有些AI条理清晰喜欢列1、2、3。 我们在利用AI的时候&#xff0c;也要学会取长补短&#xff0c;参考各家AI的回答&#xff0c;择优录用。 例如&#xff0c…

Django安装

在终端创建django项目 1.查看自己的python版本 输入对应自己本机python的版本&#xff0c;列如我的是3.11.8 先再全局安装django依赖包 2.在控制窗口输入安装命令&#xff1a; pip3.11 install django 看到Successflully 说明我们就安装成功了 python的Scripts文件用于存…

Socket 和 WebSocket 的应用

Socket&#xff08;套接字&#xff09;是计算机网络中的一个抽象层&#xff0c;它允许应用程序通过网络进行通信。套接字用于跨网络的不同主机上的应用程序之间的数据交换。在互联网中&#xff0c;套接字通常基于 TCP&#xff08;传输控制协议&#xff09;或 UDP&#xff08;用…

Materials Studio 2023安装教程(仅作分享参考)

目录 一、软件下载 二、软件介绍 2.1 软件特点 2.2 功能模块 2.3 应用领域 三、安装步骤 一、软件下载 软件名称&#xff1a;Materials Studio 2023 软件语言&#xff1a;英文 软件大小&#xff1a;2.03G 系统要求&#xff1a;Windows10或更高&#xff0c; 64位操作系…

Spark SQL大数据分析快速上手-DataFrame应用体验

【图书介绍】《Spark SQL大数据分析快速上手》-CSDN博客 《Spark SQL大数据分析快速上手》【摘要 书评 试读】- 京东图书 大数据与数据分析_夏天又到了的博客-CSDN博客 本节主要介绍如何使用DataFrame进行编程。 4.1.1 SparkSession 在旧版本中&#xff0c;Spark SQL提供…