WebSocket Demo
WebSocket Demo
WebSocket是一种在单个TCP连接上进行全双工通信的协议,它使得客户端和服务器之间的数据交换变得更加简单,允许服务端主动向客户端推送数据。在传统的HTTP协议中,客户端向服务器发出请求,服务器返回查询结果,这种单向请求的特点,注定了如果服务器有连续的状态变化,客户端要获知就非常麻烦。我们只能使用"轮询":每隔一段时候,就发出一个询问,了解服务器有没有新的信息。而WebSocket则可以解决这个问题,它可以在客户端和服务器之间建立一个持久的连接,实现双向通信。
WebSocket心跳及重连机制
WebSocket是前后端交互的长连接,在使用的过程中,遇到弱网或者网络暂时断连的情况时,服务端并没有触发onclose的事件,客户端也无法得知当前连接是否已经断开,服务端会继续向客户端发送多余链接,并且这些数据还会丢失。因此为了保证连接的可持续性和稳定性,我们需要有一套机制来检测客户端和服务端是否处于正常连接状态,WebSocket心跳重连就应运而生。
基本使用
WebSocket的基本使用方法可以参考WebSocket API。下面是一些关键方法和属性的介绍:
连接建立
ws.onopen = function () {
ws.send('Hello Server!');
}
如果要指定多个回调函数,可以使用addEventListener方法:
ws.addEventListener('open', function (event) {
ws.send('Hello Server!');
});
连接状态
WebSocket实例对象的readyState
属性返回当前状态,共有四种:
- CONNECTING:值为0,表示正在连接。
- OPEN:值为1,表示连接成功,可以通信了。
- CLOSING:值为2,表示连接正在关闭。
- CLOSED:值为3,表示连接已经关闭,或者打开连接失败。
错误处理
实例对象的onerror
属性,用于指定报错时的回调函数。
连接关闭
实例对象的onclose
属性,用于指定连接关闭后的回调函数。
数据接收
实例对象的onmessage
属性,用于指定接收到消息时的回调函数。
数据发送
实例对象的send()
方法用于向服务器发送数据。
发送缓冲
实例对象的bufferedAmount
属性,表示还有多少字节的二进制数据没有发送出去。它可以用来判断发送是否结束。
完整代码实现
下面是一个完整的WebSocket使用示例,包含了心跳检测和断线重连机制:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebSocket Demo</title>
</head>
<body>
<script type="text/javascript">
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>
具体步骤
创建WebSocket连接
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(); } }
重连操作
var lockReconnect = false; // 避免重复连接 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) } }
通过以上步骤,我们可以实现一个完整的WebSocket连接,包括心跳检测和断线重连机制,确保WebSocket连接的稳定性和可靠性。