前端对WebSocket进行封装,并建立心跳监测

news2025/6/9 21:04:53

WebSocket的介绍:

WebSocket 是一种在客户端和服务器之间进行全双工、双向通信的协议。它是基于 HTTP 协议,但通过升级(HTTP 升级请求)将连接转换为 WebSocket 协议,从而提供更高效的实时数据交换。

WebSocket 的特点:

  1. 双向通信:与传统的 HTTP 协议只能从客户端向服务器发送请求并等待响应不同,WebSocket 可以实现服务器主动向客户端推送数据,支持双向通信。

  2. 持久连接:WebSocket 连接建立后,它是持久的,可以在不重新建立连接的情况下进行多次数据交换。相比于传统的 HTTP 每次请求都需要建立新的连接,WebSocket 减少了很多开销。

  3. 实时性:由于 WebSocket 的全双工通信特性,它非常适合需要实时更新数据的应用场景,如即时聊天、在线游戏、股票行情等。

  4. 低延迟:WebSocket 建立连接后,数据可以随时在客户端和服务器之间交换,而且没有 HTTP 协议中的请求和响应过程,因此延迟非常低。

  5. 协议格式:WebSocket 协议位于应用层与 TCP 层之间,它的标准端口是 80(非加密连接)和 443(加密连接)。

WebSocket 工作原理:

  1. 连接建立:客户端发起一个 HTTP 请求,并通过 HTTP 升级请求(Upgrade 请求头)向服务器请求升级协议为 WebSocket。
  2. 协议升级:如果服务器支持 WebSocket 协议,它会响应 101 Switching Protocols,并升级为 WebSocket 协议。此时,WebSocket 连接建立成功。
  3. 数据交换:一旦连接建立,客户端和服务器可以在同一连接上发送和接收消息,直到连接被关闭。
  4. 连接关闭:无论是客户端还是服务器,都可以主动发起关闭连接。连接关闭时,双方会互相发送关闭帧(Close Frame)来通知对方。

项目需求:

由于最近项目上的大屏接口要换成WebSocket进行实时数据展示,于是需要对WebSocket进行封装,主要目标是要实现与后端持续保持心跳连接,不要让WebSocket中断;例如每10秒就要和后端通讯一次,发送和后端沟通好固定的心跳标识符,后端拿到心跳标识符就会持续保持连接,如果一直没有收到前端返回的心跳标识符,那么就会中断WebSocket的连接。

源代码

export default class WebSocketClient {
    constructor(url, callback) {
        this.url = url;           // WebSocket 服务器的 URL
        this.callback = callback; // 回调方法,用于接收数据
        this.ws = null;           // WebSocket 实例
        this.heartbeatInterval = 20000; // 心跳间隔(20秒)
        this.pingTimeout = 10000;        // ping 超时时间(10秒)
        this.heartbeatTimer = null;      // 用于存储心跳定时器
        this.pingTimer = null;           // 用于存储 ping 超时定时器
        this.reconnect = true;          // 用于判断是否需要重连
    }

    // 启动 WebSocket 连接
    start() {
        this.ws = new WebSocket(this.url);

        this.ws.onopen = () => {
            console.log("WebSocket连接成功");
            this.reconnect = true; // 连接成功,允许重连
            this.startHeartbeat(); // 连接成功后开始心跳
        };

        this.ws.onmessage = (event) => {
            this.callback(event.data); // 调用回调方法
        };

        this.ws.onerror = (error) => {
            console.error("WebSocket异常:", error);
        };

        this.ws.onclose = (event) => {
            console.log("WebSocket关闭.");
            clearInterval(this.heartbeatTimer); // 清除心跳定时器
            clearTimeout(this.pingTimer); // 清除 ping 超时定时器

            if (this.reconnect && event.code !== 1000) { // 如果是非正常关闭,进行重连
                console.log("尝试重新连接...");
                setTimeout(() => {
                    this.start(); // 5秒后重新连接
                }, 5000);
            }
        };
    }

    // 发送数据到服务器
    send(message) {
        if (this.ws && this.ws.readyState === WebSocket.OPEN) {
            this.ws.send(message);
        } else {
            console.error("消息发送失败.");
        }
    }

    // 启动心跳机制
    startHeartbeat() {
        this.heartbeatTimer = setInterval(() => {
            if (this.ws.readyState === WebSocket.OPEN) {
                this.send(JSON.stringify({ type: "heartbeat", data: "pong" })); // 与后端约定的心跳标识符,用于保持持续连接
            }
        }, this.heartbeatInterval);

        // 设置 ping 超时机制
        this.pingTimer = setTimeout(() => {
            if (this.ws.readyState !== WebSocket.OPEN) {
                console.error("超时关闭连接.");
                this.ws.close();
            }
        }, this.pingTimeout);
    }

    // 主动关闭连接
    close() {
        this.reconnect = false;  // 主动关闭时不再进行重连
        if (this.ws) {
            this.ws.close(1000, 'Closed by client'); // 主动关闭时使用 code 1000 表示正常关闭
        }
    }
}

用法

import WebSocketClient from '@/request/ws'

export default {
    data(){
        return{
            wsClient:null
        }
    },
    mounted(){
        this.wsClient = new WebSocketClient('ws://192.168.31.21:8090/ws', this.getWSMessage);
        this.wsClient.start()
    },
    methods:{
        getWSMessage(data){
            console.log(data,'ddddddddddddddd')
        },
        sendMessage(){
            let obj = { type: "555", data: "111111" }
            this.wsClient.send(JSON.stringify(obj))
        }

    },
    beforeDestroy() {
        this.wsClient.close()
    }
}

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

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

相关文章

DiMTAIC 2024 数字医学技术及应用创新大赛-甲状腺B超静态及动态影像算法赛-参赛项目

参赛成绩 项目介绍 去年参加完这个比赛之后,整理了项目文件和代码,虽然比赛没有获奖,但是参赛过程中自己也很有收获,自己一个人搭建了完整的pipeline并基于此提交了多次提高成绩,现在把这个项目梳理成博客&#xff0c…

window安装docker\docker-compose

安装前配置 打开控制面板,参照下图打开“启动或关闭windows功能”,Hyper-V 和容器需要启用 程序和功能 启动或关闭windows功能 勾选Hyper-V 安装路径配置 Docker在Windows上的默认安装路径为C:\Program Files\Docker。 以管理员身份运行CMD在D盘,dev文件夹下创建Docker文…

Jenkins的学习与使用(CI/CD)

文章目录 前言背景CI/CDJenkins简介Jenkins特性 安装Jenkins工作流程(仅供参考)安装maven和其他插件新建任务任务源码管理配置maven配置git(非必需) 尝试手动构建jar包可能遇到的错误 发布到远程服务器前置清理工作构建触发器git钩…

使用WPF的Microsoft.Xaml.Behaviors.Wpf中通用 UI 元素事件

Nuget下载之后记得要先引用下面的 xmlns:i"http://schemas.microsoft.com/xaml/behaviors" <!-- 鼠标事件 --> <i:EventTrigger EventName"MouseEnter"/> <!-- 鼠标进入 --> <i:EventTrigger EventName"MouseLeave"/&g…

Centos7.6图文安装mysql8.4详细步骤记录

1 前提条件 1.1 关闭数据库服务器的防火墙 # 关闭数据库服务器的防火墙 systemctl stop firewalld systemctl disable firewalld 1.2 关闭SELinux # 编辑 /etc/selinux/configvi /etc/selinux/config#内容更改为disabledSELINUXdisabled 1.3 卸载系统自身带的mysql&#…

AI短视频创富营

课程内容&#xff1a; 相关资料 【第一章】前期准备 001.【涨粉技巧】新账号如何快速涨粉?_ev(1).mp4 002.【带贷权限】如何开通账号带贷权限?(1).mp4 003.【费用缴纳】如何缴纳账号保证金?_ev(1).mp4 004.【账号检测】如何检测账号是否限流?(1).mp4 005.【风险规避…

spring中的@RabbitListener注解详解

基本用法主要属性1. queues / queueNames2. containerFactory3. id4. concurrency5. ackMode6. priority7. bindings 高级特性1. 消息转换器2. 手动确认3. 条件监听4. 错误处理 配置监听容器工厂注意事项完整示例循环依赖解决1. 使用 Setter 注入2. 使用 Lazy 注解3. 重构代码结…

MySQL-运维篇

运维篇 日志 错误日志 错误日志是 MySQL 中最重要的日志之一&#xff0c;它记录了当 mysqld 启动和停止时&#xff0c;以及服务器在运行过程中发生任何严重错误时的相关信息当数据库出现任何故障导致无法正常使用时&#xff0c;建议首先查看此日志。 该日志是默认开启的&am…

深度优先算法学习

1: 从 1点出发到 15点 #include <stdio.h>#define MAX_NODES 100typedef struct {int node_id;int *nextNodes;int nextNodesSize; } Node;// 假设我们有一个节点数组&#xff0c;全局保存了所有节点 Node nodes[MAX_NODES];void dfs(int node_id) {Node *node &n…

前端技能包

ES6 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title> </head> <body><script>// 变量定义var a1;let b5; // 现在使用let 定义变量// 对象解构let person{&quo…

【笔记】PyCharm 使用问题反馈与官方进展速览

#工作记录 https://youtrack.jetbrains.com/issue/IJPL-190308 【笔记】记一次PyCharm的问题反馈_the polyglot context is using an implementation th-CSDN博客 【笔记】与PyCharm官方沟通解决开发环境问题-CSDN博客 与 JetBrains 官方沟通记录&#xff08;PyCharm 相关问题…

操作系统期末版

文章目录 概论处理机管理进程线程处理机调度生产者消费者问题 死锁简介死锁的四个必要条件解决死锁的方法 存储管理链接的三种方式静态链接装入时动态链接运行时链接 装入内存的三种方式绝对装入可重定位装入动态运行时装入 覆盖交换存储管理方式连续分配**分段存储管理方式***…

自然语言处理——语言模型

语言模型 n元文法参数估计数据平滑方法加1法 神经网络模型提出原因前馈神经网络&#xff08;FNN&#xff09;循环神经网络 n元文法 大规模语料库的出现为自然语言统计处理方法的实现提供了可能&#xff0c;统计方法的成功应用推动了语料库语言学的发展。 语句 &#x1d460; …

数据库管理与高可用-MySQL高可用

目录 #1.1什么是MySQL高可用 1.1.1MySQL主主复制keepalivedhaproxy的高可用 1.1.2优势 #2.1MySQL主主复制keepalivedhaproxy的实验案例 1.1什么是MySQL高可用 MySQL 高可用是指通过技术手段确保 MySQL 数据库在面临硬件故障、软件错误、网络中断、人为误操作等异常情况时&…

免费工具-微软Bing Video Creator

目录 引言 一、揭秘Bing Video Creator 二、轻松上手&#xff1a;三步玩转Bing Video Creator 2.1 获取与访问&#xff1a; 2.2 创作流程&#xff1a; 2.3 提示词撰写技巧——释放AI的想象力&#xff1a; 三、核心特性详解&#xff1a;灵活满足多样化需求 3.1 双重使用模…

【笔记】解决MSYS2安装后cargo-install-update.exe-System Error

#工作记录 cargo-install-update.exe-System Error The code execution cannot proceed because libgit2-1.9.dll wasnot found. Reinstalling the program may fix this problem. …

银行卡二三四要素实名接口如何用PHP实现调用?

一、什么是银行卡二三四要素实名接口 输入银行卡卡号、姓名、身份证号码、手机号&#xff0c;验证此二三四要素是否一致。 二、核心价值 1. 提升风控效率 通过实时拦截冒用身份开户&#xff0c;银行卡二三四要素实名接口显著降低了人工审核成本&#xff0c;效率提升50%以上…

itvbox绿豆影视tvbox手机版影视APP源码分享搭建教程

我们先来看看今天的主题&#xff0c;tvbox手机版&#xff0c;然后再看看如何搭建&#xff1a; 很多爱好者都希望搭建自己的影视平台&#xff0c;那该如何搭建呢&#xff1f; 后端开发环境&#xff1a; 1.易如意后台管理优化版源码&#xff1b; 2.宝塔面板&#xff1b; 3.ph…

网页抓取混淆与嵌套数据处理流程

当我们在网页抓取中&#xff0c;遇到混淆和多层嵌套的情况是比较常见的挑战。混淆大部分都是为了防止爬虫而设计的&#xff0c;例如使用JavaScript动态加载、数据加密、字符替换、CSS偏移等。多层嵌套则可能是指HTML结构复杂&#xff0c;数据隐藏在多层标签或者多个iframe中。 …

高性能MYSQL:复制同步的问题和解决方案

一、复制的问题和解决方案 中断MySQL的复制并不是件难事。因为实现简单&#xff0c;配置相当容易&#xff0c;但也意味着有很多方式会导致复制停止&#xff0c;陷入混乱并中断。 &#xff08;一&#xff09;数据损坏或丢失的错误 由于各种各样的原因&#xff0c;MySQL 的复制…