理解WebSocket心跳及重连机制

在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件。这样会有:服务器会继续向客户端发送多余的链接,并且这些数据还会丢失。所以就需要一种机制来检测客户端和服务端是否处于正常的链接状态。因此就有了websocket的心跳了。还有心跳,说明还活着,没有心跳说明已经挂掉了。

1. 为什么叫心跳包呢?
它就像心跳一样每隔固定的时间发一次,来告诉服务器,我还活着。

2. 心跳机制是?
心跳机制是每隔一段时间会向服务器发送一个数据包,告诉服务器自己还活着,同时客户端会确认服务器端是否还活着,如果还活着的话,就会回传一个数据包给客户端来确定服务器端也还活着,否则的话,有可能是网络断开连接了。需要重连~

那么需要怎么去实现它呢?如下所有代码:

<html>
<head>
<meta charset="utf-8">
<title>WebSocket Demo</title>
</head>
<body>
<script type="text/javascript">
// var ws = new WebSocket("wss://echo.websocket.org");
/*
ws.onerror = function(e) {
console.log('已关闭');
};
ws.onopen = function(e) {
console.log('握手成功');
ws.send('123456789');
}
ws.onclose = function() {
console.log('已关闭');
}
ws.onmessage = function(e) {
console.log('收到消息');
console.log(e);
}
*/ var lockReconnect = false;//避免重复连接
var wsUrl = "wss://echo.websocket.org";
var ws;
var tt;
function createWebSocket() {
try {
ws = new WebSocket(wsUrl);
init();
} catch(e) {
console.log('catch');
reconnect(wsUrl);
}
}
function init() {
ws.onclose = function () {
console.log('链接关闭');
reconnect(wsUrl);
};
ws.onerror = function() {
console.log('发生异常了');
reconnect(wsUrl);
};
ws.onopen = function () {
//心跳检测重置
heartCheck.start();
};
ws.onmessage = function (event) {
//拿到任何消息都说明当前连接是正常的
console.log('接收到消息');
heartCheck.start();
}
}
function reconnect(url) {
if(lockReconnect) {
return;
};
lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
tt && clearTimeout(tt);
tt = setTimeout(function () {
createWebSocket(url);
lockReconnect = false;
}, 4000);
}
//心跳检测
var heartCheck = {
timeout: 3000,
timeoutObj: null,
serverTimeoutObj: null,
start: function(){
console.log('start');
var self = this;
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳消息,
console.log('55555');
ws.send("123456789");
self.serverTimeoutObj = setTimeout(function() {
console.log(111);
console.log(ws);
ws.close();
// createWebSocket();
}, self.timeout); }, this.timeout)
}
}
createWebSocket(wsUrl);
</script>
</body>
</html>

具体的思路如下:
1. 第一步页面初始化,先调用createWebSocket函数,目的是创建一个websocket的方法:new WebSocket(wsUrl);因此封装成函数内如下代码:

function createWebSocket() {
try {
ws = new WebSocket(wsUrl);
init();
} catch(e) {
console.log('catch');
reconnect(wsUrl);
}
}

2. 第二步调用init方法,该方法内把一些监听事件封装如下:

function init() {
ws.onclose = function () {
console.log('链接关闭');
reconnect(wsUrl);
};
ws.onerror = function() {
console.log('发生异常了');
reconnect(wsUrl);
};
ws.onopen = function () {
//心跳检测重置
heartCheck.start();
};
ws.onmessage = function (event) {
//拿到任何消息都说明当前连接是正常的
console.log('接收到消息');
heartCheck.start();
}
}

3. 如上第二步,当网络断开的时候,会先调用onerror,onclose事件可以监听到,会调用reconnect方法进行重连操作。正常的情况下,是先调用
onopen方法的,当接收到数据时,会被onmessage事件监听到。

4. 重连操作 reconnect代码如下:

var lockReconnect = false;//避免重复连接
function reconnect(url) {
if(lockReconnect) {
return;
};
lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
tt && clearTimeout(tt);
tt = setTimeout(function () {
createWebSocket(url);
lockReconnect = false;
}, 4000);
}

如上代码,如果网络断开的话,会执行reconnect方法,使用了一个定时器,4秒后会重新创建一个新的websocket链接,重新调用createWebSocket函数,
重新会执行及发送数据给服务器端。

5. 最后一步就是实现心跳检测的代码:如下:

//心跳检测
var heartCheck = {
timeout: 3000,
timeoutObj: null,
serverTimeoutObj: null,
start: function(){
console.log('start');
var self = this;
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.timeoutObj = setTimeout(function(){
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
console.log('55555');
ws.send("123456789");
self.serverTimeoutObj = setTimeout(function() {
console.log(111);
console.log(ws);
ws.close();
// createWebSocket();
}, self.timeout); }, this.timeout)
}
}

实现心跳检测的思路是:每隔一段固定的时间,向服务器端发送一个ping数据,如果在正常的情况下,服务器会返回一个pong给客户端,如果客户端通过
onmessage事件能监听到的话,说明请求正常,这里我们使用了一个定时器,每隔3秒的情况下,如果是网络断开的情况下,在指定的时间内服务器端并没有返回心跳响应消息,因此服务器端断开了,因此这个时候我们使用ws.close关闭连接,在一段时间后(在不同的浏览器下,时间是不一样的,firefox响应更快),
可以通过 onclose事件监听到。因此在onclose事件内,我们可以调用 reconnect事件进行重连操作。

理解WebSocket心跳及重连机制(五)的更多相关文章

  1. 正确理解IM长连接的心跳及重连机制,并动手实现(有完整IM源码)

    1.引言 说道“心跳”这个词大家都不陌生,当然不是指男女之间的心跳,而是和长连接相关的.顾名思义就是证明是否还活着的依据. 什么场景下需要心跳呢?目前我们接触到的大多是一些基于长连接的应用需要心跳来“ ...

  2. 从零开始实现简单 RPC 框架 9:网络通信之心跳与重连机制

    一.心跳 什么是心跳 在 TPC 中,客户端和服务端建立连接之后,需要定期发送数据包,来通知对方自己还在线,以确保 TPC 连接的有效性.如果一个连接长时间没有心跳,需要及时断开,否则服务端会维护很多 ...

  3. Netty 之 Netty生产级的心跳和重连机制

    https://blog.csdn.net/z69183787/article/details/52625095 最近工作比较忙,但闲暇之余还是看了阿里的冯家春(fengjiachun)的github ...

  4. Netty生产级的心跳和重连机制

    今天研究的是,心跳和重连,虽然这次是大神写的代码,但是万变不离其宗,我们先回顾一下Netty应用心跳和重连的整个过程: 1)客户端连接服务端 2)在客户端的的ChannelPipeline中加入一个比 ...

  5. 简易RPC框架-心跳与重连机制

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  6. WebSocket心跳检测和重连机制

    1. 心跳重连原由 心跳和重连的目的用一句话概括就是客户端和服务端保证彼此还活着,避免丢包发生. websocket连接断开有以下两证情况: 前端断开 在使用websocket过程中,可能会出现网络断 ...

  7. 初探和实现websocket心跳重连

    心跳重连缘由 在使用websocket过程中,可能会出现网络断开的情况,比如信号不好,或者网络临时性关闭,这时候websocket的连接已经断开, 而浏览器不会执行websocket 的 onclos ...

  8. 初探和实现websocket心跳重连(npm: websocket-heartbeat-js)

    提示:文章最下方有仓库地址 心跳重连缘由 websocket是前后端交互的长连接,前后端也都可能因为一些情况导致连接失效并且相互之间没有反馈提醒.因此为了保证连接的可持续性和稳定性,websocket ...

  9. 细说websocket快速重连机制

    文|马莹莹 网易智慧企业web前端开发工程师 引言 在一个完善的即时通讯应用中,websocket是极其关键的一环,它为web应用的客户端和服务端提供了一种全双工的通信机制,但由于它本身以及其底层依赖 ...

随机推荐

  1. 23种设计模式+J2EE设计模式学习笔记-初识设计模式

    设计模式简介: 设计模式是一套被反复使用的.多数人知晓的.经过分类编目的.代码设计经验的总结.(个人理解:设计模式是不关乎业务,逻辑实现,针对普遍问题的一种解决方案). 设计模式的类型: 传统23种设 ...

  2. HDU6213

    Chinese Zodiac Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)To ...

  3. Electron 应用入门 (参考官方示例)

    Electron 应用 1.去官方下案例 # 克隆示例项目的仓库 $ git clone https://github.com/electron/electron-quick-start # 进入这个 ...

  4. Jmeter在非GUI(命令行)模式下生成测试报告

    根据各大招聘网站上的需求来看,熟悉Jmeter做性能测试已经几乎成为必要条件了. 那么今天在这个给大家安利一波,怎么使用Jmeter在非GUI(命令行)模式下生成测试报告呢?? 条件准备: 1.Jme ...

  5. php+smarty轻松开发微社区/微论坛

    今天我们就来分析微社区的基本功能构成吧.首先,每个论坛最主要的是会员在对应的版块下发帖,或者在感兴趣的主题帖下跟帖盖楼.其次,会员能时时看到帖子或版块的基本信息.所以主要大块是: 前台:会员的注册登录 ...

  6. 《Inside C#》笔记(八) 接口

    接口可以认为是属于不同继承树的代码之间的行为约定.C#的接口相当于是一种特殊的抽象类,这种抽象类的内部只有虚方法. 一 接口的使用 a) 接口内部可以包含方法.属性.索引器和事件,这些成员都不在接口中 ...

  7. Android FileUtils 文件操作类

    系统路径 Context.getPackageName(); // 用于获取APP的所在包目录 Context.getPackageCodePath(); //来获得当前应用程序对应的apk文件的路径 ...

  8. [20180718]拷贝数据文件从dg库.txt

    [20180718]拷贝数据文件从dg库.txt 1.测试环境:SCOTT@book> @ ver1PORT_STRING                    VERSION        B ...

  9. [20171218]varchar2(4000)如何保存.txt

    [20171218]varchar2(4000)如何保存.txt --//以前写的,不知道为什么被删除了,现在补上. 如果一行能被存储于一个数据块(data block)中,那么其行头(row hea ...

  10. django母版页的使用

    母版页用于处理html页面相同部分内容,避免在不同的页面中重复出现 1.添加母版页 再manage.py文件相同目录下添加templates文件夹用于保存母版页html文件 2.添加母版页Base.h ...