赞
踩
为了获取实时数据,前端需要和后端保持通信,HTTP 协议只能是客户端向服务器发出请求,服务器返回查询结果。这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。一般通过以下几种方式实现即时通讯。
即时通讯:短轮询、长链接、长轮询、websocket
优点:兼容性强,实现非常简单
缺点:延迟性高,非常消耗请求资源,影响性能
优点:兼容性好,资源浪费较小
缺点:服务器 hold连接会消耗资源,返回数据顺序无保证,难于管理维护
优点:兼容性好,消息即时到达,不发无用请求
缺点:服务器维护长连接消耗资源
优点:真正意义上的实时双向通信,性能好,低延迟
缺点:独立与 http的协议,因此需要额外的项目改造,使用复杂度高,必须引入成熟的库,无法兼容低版本浏览器
轮询的效率低,非常浪费资源(因为必须不停连接,或者 HTTP 连接始终打开)。因此,在更多的时候一般都会采用websocket来实现即时通讯的需求。
WebSocket心跳及重连机制
websocket是前后端交互的长连接,在使用的过程中,遇到弱网或者网络暂时断连的情况时,服务端并没有触发onclose的事件,客户端也无法得知当前连接是否已经断开,服务端会继续向客户端发送多余链接,并且这些数据还会丢失。因此为了保证连接的可持续性和稳定性,我们需要有一套机制来检测客户端和服务端是否处于正常连接状态,websocket心跳重连就应运而生。
创建websocket实例化的时候,一般会绑定各个回调事件需要执行的函数:
<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方法,该方法内把一些监听事件封装如下:
当网络断开的时候,会先调用onerror,onclose事件可以监听到,会调用reconnect方法进行重连操作。正常的情况下,是先调用
onopen方法的,当接收到数据时,会被onmessage事件监听到。
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、重连操作 reconnect代码如下:
如果网络断开的话,会执行reconnect方法,使用了一个定时器,4秒后会重新创建一个新的websocket链接,重新调用createWebSocket函数,重新会执行及发送数据给服务器端。
var lockReconnect = false;//避免重复连接
function reconnect(url) {
if(lockReconnect) {
return;
};
lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
tt && clearTimeout(tt);
tt = setTimeout(function () {
createWebSocket(url);
lockReconnect = false;
}, 4000);
}
4、 最后一步就是实现心跳检测的代码:
//心跳检测 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) } }
更多文章__> >> 码砖猿的技术博客
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。