理解WebSocket⼼跳及重连机制(五)
理解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://");
/*
console.log('已关闭');
};
console.log('握⼿成功');
ws.send('123456789');
}
console.log('已关闭');
}
console.log('收到消息');
console.log(e);
}
*/
var lockReconnect = false;//避免重复连接
var wsUrl = "wss://";
var ws;
var tt;
function createWebSocket() {
try {
ws = new WebSocket(wsUrl);
init();
} catch(e) {
console.log('catch');
reconnect(wsUrl);
}
}
function init() {
console.log('链接关闭');
reconnect(wsUrl);
};
console.log('发⽣异常了');
reconnect(wsUrl);
};
//⼼跳检测重置
heartCheck.start();
};
//拿到任何消息都说明当前连接是正常的
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);websocket和socket
}
}
2. 第⼆步调⽤init⽅法,该⽅法内把⼀些监听事件封装如下:
function init() {
console.log('链接关闭');
reconnect(wsUrl);
};
console.log('发⽣异常了');
reconnect(wsUrl);
};
//⼼跳检测重置
heartCheck.start();
};
/
/拿到任何消息都说明当前连接是正常的
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事件进⾏重连操作。