SignalR中的重连机制和心跳监测机制详解

news2025/1/15 8:14:01

一. 重连机制

声明:
  本节仅介绍重连机制和心跳监测机制,基于Core 3.1框架,至于SignalR其它的一些基本使用,包括引入、Hub、配置等常规操作,在本节中不介绍,后续写Core下的SignalR

  1. 说明
      默认是没有重连机制的,需要加上withAutomaticReconnect开启重连,默认重连4次,分别时间间隔为:0、2、10和30秒 (指掉线的瞬间马上重连、再过2s重连、再过10s重连,再过20s重连,这里指的是间隔,而不是叠加)。当然也可以自行配置,eg:.withAutomaticReconnect([10000, 4000, 10000, 10000])。

PS: 经过测试,这里有一个现象,比如 先断网,触发掉线机制,然后恢复网,走重连机制,恢复后的重连的第一次是连不上的,必须第二次才能连上。第一次报错:'Error: WebSocket closed with status code: 1006 ().

//安卓手机的写法
var connection = new signalR.HubConnectionBuilder().withUrl("http://47.92.198.126:8088/chathub")
                 .withAutomaticReconnect([10000, 4000, 10000, 10000])
                 .build();    
//苹果的手机的写法 (需要跳过协商)          
var connection = new signalR.HubConnectionBuilder().withUrl("http://47.92.198.126:8088/chathub", {
                        skipNegotiation: true, //针对webSocket为默认协议的时候,可以跳过协商
                        transport: signalR.HttpTransportType.WebSockets
                    })
                 .withAutomaticReconnect([3000, 4000, 10000, 10000])
                 .build();

我们发现上述代码,安卓和IOS写法不一样,这里是因为IOS系统仅支持WebSocket协议,所以要手动指定,并且跳过协商。
2. 重连的回调

(1). onreconnecting:重连之前调用 (只有在掉线的一瞬间,只进入一次),状态为:Reconnecting 。

(2). onreconnected:(默认4次重连),任何一次只要回调成功,调用,状态为:Connected 。

(3). onclose:(默认4次重连) 全部都失败后,调用,状态为:Disconnected。

  1. 实战测试

分析下面代码,建立连接后,手机断网,输出1,进入了 onreconnecting 回调;大约过 3s 后,连接上网,即已经过了第一次重连的时间,进入第2个 4s的重连,过了4s,走重连机制,这个时候属于恢复网络后的第一次,是重连不上的,需要到了第三个重连机制,再过10s后,重连成功。

如果一直断网,4次重连全部失败,则会进入onclose回调。

<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <title></title>
        <script src="js/jquery.js" type="text/javascript" charset="utf-8"></script>
        <script src="js/signalr.js" type="text/javascript" charset="utf-8"></script>
        <script type="text/javascript">
            $(function() {
                //苹果的手机的写法 (需要跳过协商)               
                var connection = new signalR.HubConnectionBuilder().withUrl("http://XXX:8088/chathub", {
                        skipNegotiation: true, //针对webSocket为默认协议的时候,可以跳过协商
                        transport: signalR.HttpTransportType.WebSockets
                    })
                    .withAutomaticReconnect([3000, 4000, 10000, 10000])
                    .build();            
                //建立连接
                $('#j_btn1').click(function() {
                    connection.start().then(function() {
                        console.log("连接成功");
                        $('#j_hb').append('<div>连接成功</div>')
                    }).catch(function(err) {
                        $('#j_hb').append('<div>' + err.toString() + '</div>')
                        return console.error(err.toString());
                    });
                });
                //发送消息
                $("#j_send").click(function() {
                    connection.invoke("SendMessage", $("#j_content").val()).catch(function(err) {
                        $('#j_hb').append('<div>' + err.toString() + '</div>');
                        return console.error(err.toString());
                    });

                });
                //接收消息
                connection.on("ReceiveMessage", function(msg) {
                    console.log(msg);
                    $('#j_hb').append('<div>' + msg + '</div>')
                });

                //下面测试断线重连机制 ,
                //重连之前调用 (只有在掉线的一瞬间,只进入一次)
                connection.onreconnecting((error) => {
                    console.log(1);
                    $('#j_hb').append('<div>1</div>');
                    console.log(connection.state);
                    console.log(connection.state === signalR.HubConnectionState.Reconnecting);

                });
                //(默认4次重连),任何一次只要回调成功,调用
                connection.onreconnected((connectionId) => {
                    console.log(2);
                    $('#j_hb').append('<div>2</div>');
                    console.log(connection.state);
                    console.log(connection.state === signalR.HubConnectionState.Connected);

                });
                //(默认4次重连) 全部都失败后,调用
                connection.onclose((error) => {
                    console.log('3');
                    $('#j_hb').append('<div>3</div>');
                    console.log(connection.state);
                    console.assert(connection.state === signalR.HubConnectionState.Disconnected);
                });
            });
        </script>
    </head>
    <body>
        <br /> <br /> <br /> <br /> <br />
        <input type="text" id="j_content" value="" />
        <button id="j_btn1">建立连接</button>
        <button id="j_send">发送消息</button>
        <br /> <br /> <br /> <br /> <br />
        <div id="j_hb">

        </div>
    </body>
</html>

二. 心跳监测机制

  1. 何为心跳监测机制

当客户端和app端不发送消息的时候,这个时候需要一种机制,来相互ping,保证客户端和服务器端是连接状态的,从而一直保证在线状态哦。这里有两套机制来保证,分别是告诉客户端,服务器是正常的;告诉服务器端,客户端是在线的。SignalR提供了两套监测机制,来保证长久连接在线不掉,或者删掉不必要的客户端,释放资源。

2. 配置说明

(1). 服务端配置

在这里插入图片描述
A. clientTimeoutInterval:表示客户端如果在30s内没有向服务器发送任何消息,那么服务器端则会认为客户端已经断开连接了,则进入OnDisconnectedAsync方法, 但实际上 客户端此时可能并没有断开连接,或者断开连接还需要一段时间,因为客户端断开连接是走的另外一套机制的。【以服务器端为基准,判断客户端是否断开连接,从而断开服务器端连接】
B. keepAliveinterval: 表示如果服务器未在15s内向客户端发送消息,在15s的时候服务器会自动ping客户端,是连接保持打开的状态。【用于控制服务端自动ping客户端的时间】
(2). 客户端配置
在这里插入图片描述
 A. serverTimeoutInMilliseconds:表示客户端如果在30s内收到服务器端发送的消息,客户端会断开连接,进入onclose事件。(前提是没有启动:自动重连机制,已测试)。 它和服务器端的keepAliveinterval是一对的,该值必须比服务器端的serverTimeoutInMilliseconds值大,建议是它的两倍。【是以客户端为基准,判断服务器端是否断开连接,从而断开客户端连接】

B. keepAliveIntervalInmillisecods:【用户控制客户端自动ping服务器端的时间】。 指如果客户端在15s内没有发送任何消息,则15s的时候客户端会自动ping一下服务器端,从而告诉服务器端,我在线。如果15s内发消息,这个时间间隔将会被重置。

(3). 两套机制 (实际中,两套机制相互配合使用)

A. 以客户端为基准的机制 (客户端主动进 onclose回调)

客户端配置:serverTimeoutInMilliseconds + 服务端端配置:keepAliveinterval ,建议serverTimeoutInMilliseconds 的值是 keepAliveinterval 的两倍,从而保证客户端不进入 onclose回调,不掉线。

代码分享:下面代码的配置就是默认配置,客户端配置30s没有收到服务器端发过来的信息,则认为服务器端异常,客户端掉线,进入onclose回调;服务器端配置为15s没有向客户端发送消息,则需要主动ping一下客户端,按照默认这种Server 15s,Client 30s的配置,在网络通畅的情况下,客户端是不会掉线的。

PS:此处如果改个非正常配置,比如客户端 serverTimeoutInMilliseconds 配置10s,服务器端
keepAliveInterval 配置20s,经测试,你会发现,如果客户端在10s内没有收到任何消息,则会吊销,进入onclose回调。

public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            //此处是做SignalR的全局配置,也可以去下面的集线器出配置单独的,单独的优先级> 此处全局的
            services.AddSignalR(hubOptions =>
            {       
                //服务器端向客户端 ping的间隔
                hubOptions.KeepAliveInterval = TimeSpan.FromSeconds(15);
            });
        }

B. 以服务端为基准的机制

客户端配置:keepAliveIntervalInmillisecods + 服务端配置:clientTimeoutInterval,建议 clientTimeoutInterval 的值是 keepAliveIntervalInmillisecods 的两倍,从而保证不进服务器端的 OnDisconnectedAsync 回调,即不掉线。

代码分享:下面代码是默认配置,客户端配置15s内没有向服务器发送任何消息,则自动ping一下服务器端;服务器端配置30s没有收到客户端发送的消息,则认为客户端已经掉线(虽然客户端此时可能没有掉线);在网络通畅的情况下,服务器端是不会进入OnDisconnectedAsync回调的。

var connection = new signalR.HubConnectionBuilder().withUrl("http://XXXX:8088/chathub").build();    
connection.keepAliveIntervalInMilliseconds= 15000;  //15s
public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllersWithViews();
            //此处是做SignalR的全局配置,也可以去下面的集线器出配置单独的,单独的优先级> 此处全局的
            services.AddSignalR(hubOptions =>
            {       
                //要求30s内必须收到客户端发的一条消息,如果没有收到,那么服务器端则认为客户端掉了
                hubOptions.ClientTimeoutInterval= TimeSpan.FromSeconds(30);
            });
        }

在这里插入图片描述

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

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

相关文章

汽车Type-C接口:特点与要求解析

汽车Type-C接口的需求增长 随着汽车科技的不断发展&#xff0c;车载电子设备的功能和数量不断增加&#xff0c;因此&#xff0c;对于汽车Type-C接口的需求也在逐渐增长。作为一种高速、多功能的连接标准&#xff0c;汽车Type-C接口在车载设备连接中扮演着越来越重要的角色。 …

45. 【Android教程】内容提供者 - Content Provider

本节学习最后一个 Android 组件——内容提供者。顾名思义&#xff0c;它可以用来给其他的 App 提供各种内容&#xff0c;比如 Android 自带的短信、联系人、日历等等都是一个普通的 App&#xff0c;当你需要这些内容的时候&#xff0c;就可以向它们的 Content Provider 发起请求…

Siddhi 快速入门-安装Siddhi 编辑器

第一次使用Siddhi 在本节中&#xff0c;我们将使用 Siddhi 工具发行版 — Siddhi 的服务器版本&#xff0c;具有带有 GUI 的复杂的基于 Web 的编辑器&#xff08;称为“Siddhi 编辑器”&#xff09;&#xff0c;您可以在其中编写 Siddhi 应用程序并模拟事件来测试您的场景。 …

git 冲突与解决冲突

目录 1.使用 git 解决冲突 GIT 常用命令 制造冲突 解决冲突 2.使用 IDEA 解决冲突 产生冲突 解决冲突 1.使用 git 解决冲突 GIT 常用命令 命令作用git clone克隆git init初始化git add 文件名添加到暂存区git commit -m " 日志信息" 文件名提交到本地库git st…

LabVIEW连接PostgreSql

一、安装ODBC 下载对应postgreSQL版本的ODBC 下载网址&#xff1a;http://ftp.postgresql.org/pub/odbc/versions/msi/ 下载好后默认安装就行&#xff0c;这样在ODBC数据源中才能找到。 二、配置系统DSN 实现要新建好要用的数据库&#xff0c;这里的用户名&#xff1a;postg…

第十五届蓝桥杯省赛第二场C/C++B组G题【最强小队】题解

20pts 枚举所有可能的左端点、右端点&#xff0c;时间复杂度 O ( n 2 ) O(n^2) O(n2)。 对于每个区间进行遍历检测&#xff0c;时间复杂度 O ( n 3 ) O(n^3) O(n3)。 100pts 由于数据范围为 1 0 5 10^5 105&#xff0c;所以肯定只能进行一次枚举。 我们尝试枚举右端点&…

揭秘航空之心:飞机涡轮发动机3D模型震撼登场

在浩瀚的蓝天下&#xff0c;飞机如同矫健的雄鹰&#xff0c;展翅翱翔。而支撑起这雄鹰的力量之源&#xff0c;便是其心脏——涡轮发动机。今天&#xff0c;我们将通过山海鲸可视化搭建的逼真的飞机涡轮3D模型&#xff0c;揭开航空工业的神秘面纱。 飞机涡轮发动机3D模型不仅是对…

《A Discriminative Feature Learning Approach for Deep Face Recognition》阅读笔记

论文标题 《A Discriminative Feature Learning Approach for Deep Face Recognition》 一种用于深度人脸识别的判别性特征学习方法 作者 Yandong Wen、Kaipeng Zhang、Zhifeng Li 和 Yu Qiao 来自深圳市计算机视觉与专利重点实验室、中国科学院深圳先进技术研究院和香港中…

网上打印资料多少钱一张?网上打印价格是多少?

在数字化时代&#xff0c;网上打印服务正逐渐成为一种便捷、高效的打印解决方案。对于许多需要打印资料的用户来说&#xff0c;了解网上打印的价格和服务质量至关重要。那么&#xff0c;网上打印资料到底多少钱一张&#xff1f;网上打印价格又是如何呢&#xff1f;今天&#xf…

【设计模式】单例模式|最常用的设计模式

写在前面 单例模式是最常用的设计模式之一&#xff0c;虽然简单&#xff0c;但是还是有一些小坑点需要注意。本文介绍单例模式并使用go语言实现一遍单例模式。 单例模式介绍 简介 单例模式保证一个类仅有一个实例&#xff0c;并提供一个访问它的全局访问点。 使用场景&#…

超市火灾烟雾蔓延及人员疏散的matlab模拟仿真,带GUI界面

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.本算法原理 5.完整程序 1.程序功能描述 出口在人员的视野范围内时&#xff0c;该元胞选择朝向引导点的方向运动。出口不在人员的视野范围内时&#xff0c;作随机运动&#xff0c;8个方向的运动概率相等。…

短视频素材怎么做?视频素材库那个好?

在这个视频内容占据主导的时代&#xff0c;高质量的无水印视频素材不仅能够丰富视觉体验&#xff0c;还能显著提升你的作品吸引力。为了帮助你在广阔的创意海洋中航行&#xff0c;下面介绍的一系列视频素材网站将为你的项目注入新的活力&#xff0c;让每个创意的火花都能闪耀发…

Spring Boot集成Redisson实现延迟队列

项目场景&#xff1a; 在电商、支付等领域&#xff0c;往往会有这样的场景&#xff0c;用户下单后放弃支付了&#xff0c;那这笔订单会在指定的时间段后进行关闭操作&#xff0c;细心的你一定发现了像某宝、某东都有这样的逻辑&#xff0c;而且时间很准确&#xff0c;误差在1s内…

K-近邻算法的 sklearn 实现

实验目的与要求 掌握基于 K-近邻分类算法的编程方法通过编程理解 K-近邻分类算法和该算法的基本步骤 实验器材 硬件&#xff1a;PC 机&#xff08;参与实验的学生每人一台&#xff09;软件环境&#xff1a;Python3.7 Pycharm 实验内容 使用 sklearn 库中的 neighbors 模块实…

【java、maven环境变量配置问题】

这里写目录标题 软件版本查询所遇问题及解决方法1、java环境变量修改后不起效果&#xff1a;变量值2、java环境变量修改后不起效果&#xff1a;变量名结论&#xff1a; 软件版本查询 查询 java jdk 版本&#xff1a;java -version 查询 maven 版本&#xff1a; mvn -v 所遇问…

如何安装最新版Docker Compose?

Docker Compose 是一个用于定义和运行多容器 Docker 应用程序的工具。通过 Compose&#xff0c;您可以使用 YAML 文件来配置应用服务&#xff0c;然后只需一个简单的命令便能创建和启动所有服务。在本篇博客中&#xff0c;我们将详细介绍如何在 Linux 系统上安装 Docker Compos…

恭喜!喜提美国匹兹堡大学儿童医院访问学者邀请函

➡️【院校简介】 匹兹堡UPMC儿童医院该院是匹兹堡大学医学中心的一部分&#xff0c;也是大匹兹堡唯一一家专门护理26岁以下婴儿&#xff0c;儿童&#xff0c;青少年和年轻人的医院。该医院隶属于匹兹堡大学医学院&#xff0c;设有一个获得州级认证的一级儿科创伤中心&#xf…

ESP32开发WebSocket报错TRANSPORT_WS: Sec-WebSocket-Accept not found

我的芯片是ESP32-S3&#xff0c;用ESP-IDF框架进行开发的时候&#xff0c;用官方的WebSocket的example创建了项目。然后把WebSocket连接uri替换为自己的服务器后&#xff0c;运行到esp_websocket_client_start开始连接后&#xff0c;直接报错&#xff1a; E (10615) TRANSPORT…

C++|运算符重载(3)|日期类的计算

前面介绍了运算符重载相关规则和方法&#xff0c;今天用运算重载函数实现对日期类的操作。 目录 前面准备 实现功能&#xff1a; -运算符 Date类和int 相减 Date类和Date类相减 运算符 &#xff0c;-运算符 ,!运算符 >,>运算符 <,<运算符 &#xff0c;-…

MIS微调SAM模型实时交互UI界面

前言 SAM模型的基本介绍可见SAM&#xff08;Segment Anything Model&#xff09;大模型使用--point prompt_sam大模型-CSDN博客 针对Meta团队去年发布的SAM大模型在医学图像分割领域表现性能较差的情况&#xff0c;笔者收集了一些MIS领域的数据集对SAM的架构进行fine tune&am…