====测试代码:

==index.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
abc
</div>
</body>
<script type="text/javascript" src="js/websocket.js"></script>
<script src="js/client.js"></script>
</html>

==websocket.js

var lockReconnect = false; //避免ws重复连接
var ws = null; // 判断当前浏览器是否支持WebSocket
var wsUrl = null;
var config = {}; function socketLink(set) {
config = set;
wsUrl = config.url;
createWebSocket(wsUrl); //连接ws
} function createWebSocket(url) {
try {
if ('WebSocket' in window) {
ws = new WebSocket(url, 'echo-protocol');
} else if ('MozWebSocket' in window) {
ws = new MozWebSocket(url, 'echo-protocol');
} else {
alert("您的浏览器不支持websocket")
}
initEventHandle();
} catch (e) {
reconnect(url);
console.log(e);
}
} function initEventHandle() {
ws.onclose = function() {
reconnect(wsUrl);
console.log("llws连接关闭!" + new Date().toUTCString());
};
ws.onerror = function() {
reconnect(wsUrl);
console.log("llws连接错误!");
};
ws.onopen = function() {
heartCheck.reset().start(); //心跳检测重置
console.log("llws连接成功!" + new Date().toUTCString());
config.open(ws)
};
ws.onmessage = function(event) { //如果获取到消息,心跳检测重置
heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的
config.msg(event.data,ws)
};
}
// 监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
window.onbeforeunload = function() {
ws.close();
} function reconnect(url) {
if (lockReconnect) return;
lockReconnect = true;
setTimeout(function() { //没连接上会一直重连,设置延迟避免请求过多
createWebSocket(url);
lockReconnect = false;
}, 2000);
} //心跳检测
var heartCheck = {
timeout: 10000, //9分钟发一次心跳
timeoutObj: null,
serverTimeoutObj: null,
reset: function() {
clearTimeout(this.timeoutObj);
clearTimeout(this.serverTimeoutObj);
return this;
},
start: function() {
var self = this;
this.timeoutObj = setTimeout(function() {
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
ws.send("ping");
console.log("ping!")
self.serverTimeoutObj = setTimeout(function() { //如果超过一定时间还没重置,说明后端主动断开了
console.log("try=close")
ws.close(); //这里为什么要在send检测消息后,倒计时执行这个代码呢,因为这个代码的目的时为了触发onclose方法,这样才能实现onclose里面的重连方法
          //所以这个代码也很重要,没有这个方法,有些时候发了定时检测消息给后端,后端超时(我们自己设定的时间)后,不会自动触发onclose方法。我们只有执行ws.close()代码,让ws触发onclose方法
          //的执行。如果没有这个代码,连接没有断线的情况下而后端没有正常检测响应,那么浏览器时不会自动超时关闭的(比如谷歌浏览器),谷歌浏览器会自动触发onclose
          //是在断网的情况下,在没有断线的情况下,也就是后端响应不正常的情况下,浏览器不会自动触发onclose,所以需要我们自己设定超时自动触发onclose,这也是这个代码的
          //的作用。
}, self.timeout)
}, this.timeout)
}
}

心跳检测的目的时什么呢?

一个是为了定时发送消息,使连接不超时自动断线,可能后端设了超时时间就会自动断线,所以需要定时发送消息给后端,让后端服务器知道连接还在通消息不能断。

二来是为了检测在正常还连接着的情况下,判断后端是否正常,如果我们发了一个定时检测给后端,后端按照约定要下发一个检测消息给前端,这样才是正常的。

可是如果后端没有正常下发呢,我们就要设定一下超时要重连了,我们把重连写在了onclose里面,当时正常连接的情况下,超时未能响应检测消息的情况下,浏览器不会自动断掉触发onclose,所以需要我们手动触发,也就是在超时里写一个ws.close()让ws关闭触发onclose方法,实现重连。

==浏览器会触发onclose的情况是断网断线的情况下,当时正常连接还未断线,浏览器时不会自动触发onclose的,所以就有超时手动触发onclose的必要。

self.serverTimeoutObj = setTimeout(function() { //如果超过一定时间还没重置,说明后端主动断开了
console.log("try=close")
ws.close(); //这里为什么要在send检测消息后,倒计时执行这个代码呢,因为这个代码的目的时为了触发onclose方法,这样才能实现onclose里面的重连方法
          //所以这个代码也很重要,没有这个方法,有些时候发了定时检测消息给后端,后端超时(我们自己设定的时间)后,不会自动触发onclose方法。我们只有执行ws.close()代码,让ws触发onclose方法
          //的执行。如果没有这个代码,连接没有断线的情况下而后端没有正常检测响应,那么浏览器时不会自动超时关闭的(比如谷歌浏览器),谷歌浏览器会自动触发onclose
          //是在断网的情况下,在没有断线的情况下,也就是后端响应不正常的情况下,浏览器不会自动触发onclose,所以需要我们自己设定超时自动触发onclose,这也是这个代码的
          //的作用。 }, self.timeout)
ws.onopen = function() {
heartCheck.reset().start(); //心跳检测重置 在open的时候触发心跳检测
console.log("llws连接成功!" + new Date().toUTCString());
config.open(ws)
};
ws.onmessage = function(event) { //如果获取到消息,心跳检测重置
heartCheck.reset().start(); //拿到任何消息都说明当前连接是正常的 //如果后端有下发消息,那么就会重置初始化心跳检测,除非超时没下发,那么就会触发onclose
       //然后触发重连
config.msg(event.data,ws)
};

==client.js

var number=0;
var config = {
url: 'ws://localhost:8080/',
open: (ws) => {
function sendNumber() {
if (ws.readyState === ws.OPEN) {
number = number+1;
ws.send(number.toString());
setTimeout(sendNumber, 1000);
}
}
sendNumber()
},
msg: (data) => {
console.log(data, "msg")
}
}
socketLink(config)

==node 后端测试代码:

#!/usr/bin/env node

var WebSocketServer = require('websocket').server;
var http = require('http'); var server = http.createServer(function(request, response) {
console.log((new Date()) + ' Received request for ' + request.url);
response.writeHead(404);
response.end();
});
server.listen(8080, function() {
console.log((new Date()) + ' Server is listening on port 8080');
}); wsServer = new WebSocketServer({
httpServer: server,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: false
}); function originIsAllowed(origin) {
console.log(origin,"origin")
// put logic here to detect whether the specified origin is allowed.
return true;
} wsServer.on('request', function(request) {
if (!originIsAllowed(request.origin)) {
// Make sure we only accept requests from an allowed origin
request.reject();
console.log((new Date()) + ' Connection from origin ' + request.origin + ' rejected.');
return;
} var connection = request.accept('echo-protocol', request.origin);
console.log((new Date()) + ' Connection accepted.');
connection.on('message', function(message) {
if (message.type === 'utf8') {
console.log('Received Message: ' + message.utf8Data);
//connection.sendUTF(message.utf8Data); //注释掉是为了测试前端在没后端响应却连接着的情况下,是什么反应。
} else if (message.type === 'binary') {
console.log('Received Binary Message of ' + message.binaryData.length + ' bytes');
connection.sendBytes(message.binaryData);
}
});
connection.on('close', function(reasonCode, description) {
console.log((new Date()) + ' Peer ' + connection.remoteAddress + ' disconnected.');
});
});

javascript websocket 心跳检测机制介绍的更多相关文章

  1. netty心跳检测机制

    既然是网络通信那么心跳检测肯定是离不开的,netty心跳检测分为读.写.全局 bootstrap.childHandler(new ChannelInitializer<SocketChanne ...

  2. 面试官:Netty心跳检测机制是什么,怎么自定义检测间隔时间?

    哈喽!大家好,我是小奇,一位热爱分享的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 书接上回,昨天在地里干了一天的 ...

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

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

  4. Netty 中的心跳检测机制

    心跳检测一般存在于建立长连接 或者 需要保活的场景. 心跳的使用场景 长连接的应用场景非常的广泛,比如监控系统,IM系统,即时报价系统,推送服务等等.像这些场景都是比较注重实时性,如果每次发送数据都要 ...

  5. Oracle RAC/Clusterware 多种心跳heartbeat机制介绍 RAC超时机制分析

    ORACLE RAC中最主要存在2种clusterware集群件心跳 &  RAC超时机制分析: 1.Network Heartbeat 网络心跳 每秒发生一次: 10.2.0.4以后网络心跳 ...

  6. 分析dubbo心跳检测机制

    目的: 维持provider和consumer之间的长连接 实现: dubbo心跳时间heartbeat默认是60s,超过heartbeat时间没有收到消息,就发送心跳消息(provider,cons ...

  7. Netty — 心跳检测和断线重连

    一.前言 由于在通信层的网络连接的不可靠性,比如:网络闪断,网络抖动等,经常会出现连接断开.这样对于使用长连接的应用而言,当突然高流量冲击势必会造成进行网络连接,从而产生网络堵塞,应用响应速度下降,延 ...

  8. 理解WebSocket心跳及重连机制(五)

    理解WebSocket心跳及重连机制 在使用websocket的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发onclose的事件.这样会有:服务器会继续向客户端发送多余的 ...

  9. 【Netty】利用Netty实现心跳检测和重连机制

    一.前言 心跳机制是定时发送一个自定义的结构体(心跳包),让对方知道自己还活着,以确保连接的有效性的机制.   我们用到的很多框架都用到了心跳检测,比如服务注册到 Eureka Server 之后会维 ...

随机推荐

  1. NewSQL和TiDB入门

    TiDB已经在项目中使用,从了解来看,它主要解决的是分布式事务的问题,而我们实际使用场景,却是大数据量下不需要关注分表: 最近实在忙加懒,一直没时间看TiDB的原理.今天看了下PingCAP3篇入门介 ...

  2. java Boolean和boolean的区别

    Boolean b1=new Boolean("false"); Boolean b2=new Boolean("tRue"); Boolean b3=new ...

  3. Visual C++ 6.0中if语句的常见问题

    # include <stdio.h> int main (void) { > )//如果在第四行加分号的话,编译的时候就会在第六行出错 printf("你好\n" ...

  4. Spring Security框架下Restful Token的验证方案

    项目使用Restful的规范,权限内容的访问,考虑使用Token验证的权限解决方案. 验证方案(简要概括): 首先,用户需要登陆,成功登陆后返回一个Token串: 然后用户访问有权限的内容时需要上传T ...

  5. zznuoj 1540 : 直线与圆

    题目描述 给出一个圆的圆心坐标与圆的半径,和一条直线上的两点坐标,求这条直线与圆有多少个交点. 输入 输入3个实数x,y,r值分别表示圆心坐标与圆的半径,输入4个实数x1,y1,x2,y2表示直线上的 ...

  6. PHP全局变量,超全局变量

    php中有许多超全局变量,这意味着它们在一个脚本的全部作用域中都可用.在函数或方法中无需执行 global $variable; 就可以访问它们. 这些超全局变量是: $GLOBALS    引用全局 ...

  7. Ubuntu 16.04 LTS 安装 miniconda

    Ubuntu 16.04 LTS 安装 miniconda 下载 miniocnda 的 bash 文件下载链接 https://conda.io/miniconda.html ,我选择的是 64-b ...

  8. python中的time模块和datetime模块

    >>> import time>>> time.time()1511330865.656656>>> time.localtime(time.ti ...

  9. 引擎设计跟踪: 为什么Blade可以用Clang编译

    最近在使用VS2015 Community, 在添加了shared items project, 并把源代码加入shared items, 添加Android工程编译的时候, 发现可以用Clang正常 ...

  10. lua 匹配空白符

    lua 支持的所有字符类: .     任意字符%s 空白符 空白字符一般包括空格.换行符\n.制表符\t以及回到行首符\r%p 标点字符%c 控制字符%d 数字%x 十六进制数字%z 代表0的字符% ...