理解WebSocket心跳及重连机制javascript
在使用websocket的过程当中,有时候会遇到网络断开的状况,可是在网络断开的时候服务器端并无触发onclose的事件。这样会有:服务器会继续向客户端发送多余的连接,而且这些数据还会丢失。因此就须要一种机制来检测客户端和服务端是否处于正常的连接状态。所以就有了websocket的心跳了。还有心跳,说明还活着,没有心跳说明已经挂掉了。html
1. 为何叫心跳包呢?
它就像心跳同样每隔固定的时间发一次,来告诉服务器,我还活着。java
2. 心跳机制是?
心跳机制是每隔一段时间会向服务器发送一个数据包,告诉服务器本身还活着,同时客户端会确认服务器端是否还活着,若是还活着的话,就会回传一个数据包给客户端来肯定服务器端也还活着,不然的话,有多是网络断开链接了。须要重连~web
那么须要怎么去实现它呢?以下全部代码:后端
<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事件监听到。websocket
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函数,
从新会执行及发送数据给服务器端。socket
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事件进行重连操做。