在vue中使用websocket以及心跳检测

前言

在使用 websocket 的过程中,有时候会遇到网络断开的情况,但是在网络断开的时候服务器端并没有触发 onclose 的事件。这样会有:服务器会继续向客户端发送多余的链接,并且这些数据还会丢失。所以就需要一种机制来检测客户端和服务端是否处于正常的链接状态。因此就有了 websocket 的心跳了。还有心跳,说明还活着,没有心跳说明已经挂掉了。

为什么叫心跳包呢?

它就像心跳一样每隔固定的时间发一次,来告诉服务器,我还活着。

心跳机制是?

心跳机制是每隔一段时间会向服务器发送一个数据包,告诉服务器自己还活着,同时客户端会确认服务器端是否还活着,如果还活着的话,就会回传一个数据包给客户端来确定服务器端也还活着,否则的话,有可能是网络断开连接了。需要重连~

实现

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
<script>
export default {
data() {
return {
WebSocket: null,
timeout: 15 * 1000, //心跳检测间隔 ms
severTimeout: 3 * 1000, //服务器超时时间,也就是websocket关闭重启时间 ms
reconnectTimeout: 3 * 1000, //websocket重连时间间隔 ms
timeoutObj: null,
serverTimeoutObj: null,
lockReconnect: false //连接状态标识
};
},
computed: {},
watch: {},
mounted() {
this.initWebSocket();
},
beforeDestroy() {
this.wsClose();
},
methods: {
/*=============================================
= WebSocket 推送 =
=============================================*/
//websocket初始化
initWebSocket() {
try {
this.createWebSocket();
} catch (e) {
reconnect();
}
},
// websocket实例
createWebSocket() {
const url = "";
//
this.WebSocket = new WebSocket(url);
//
this.WebSocket.onopen = res => {
this.reset();
this.wsOnOpen(res);
};
this.WebSocket.onmessage = e => {
this.reset();
this.wsOnMessage(e);
};
this.WebSocket.onerror = err => {
this.reconnect();
this.wsOnError(err);
};
this.WebSocket.onclose = res => {
this.reconnect();
this.wsOnClose(res);
};
},

/* 事件 */
wsOnOpen(res) {
window.console.log("ws推送连接成功!");
},
wsOnMessage(e) {},
wsOnClose(res) {
window.console.log("ws推送已关闭!");
},

/* 方法 */
wsSend(text) {
text = JSON.stringify(text);
this.WebSocket.send(text);
},
wsClose() {
this.WebSocket.close();
},

/* 心跳检测 */
start() {
this.timeoutObj = setTimeout(() => {
// send内容不可更改!!!发送内容与后端商定
this.wsSend({ a: 1 });
this.serverTimeoutObj = setTimeout(() => {
this.wsClose();
}, this.severTimeout);
}, this.timeout);
},
reset() {
this.timeoutObj && clearTimeout(this.timeoutObj);
this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
this.start();
},

/* 计数,避免websocket重复连接 */
reconnect() {
if (this.lockReconnect) {
return;
}
this.lockReconnect = true;
//没连接上会一直重连,设置延迟避免请求过多
// tt && clearTimeout(tt);
setTimeout(() => {
this.initWebSocket();
this.lockReconnect = false;
}, this.reconnectTimeout);
}

/*===== End of WebSocket 推送 ======*/
}
};
</script>

其中发送的内容需要与后端商议,在客户端发送心跳包之后,服务端再返回一个心跳包,这样前端就可以分辨心跳包与其他消息推送了。