Websocket详解和封装
2023-03-21 本文已影响0人
扶得一人醉如苏沐晨
一、 websocket 是什么?
websocket 是一种网络通信协议,与 http 语义一样,但功能不一样
http 也是一种网络通信协议,为什么不用 http 而用 websocket ?
二、websocket 与 http 有什么区别?
websocket 通信可由服务器发起,也可以由客户端发起。可以实现客户端与服务端长连接
http 通信只能由客户端发起。

三、WebSocket 触发事件
以下是 WebSocket 对象的相关事件。

四、WebSocket 方法
假定我们使用了以上代码创建了 Socket 对象:this.Socket.close()/this.Socket.send()

WebSocket 组件封装(包含健康检查和心跳机制)
<template></template>
<script>
import { mapGetters } from "vuex";
export default {
data () {
return {
// ws
maxReconnect: 3, // 最大重连次数,-1代表无限重连
reconnectTime: 0, // 重连尝试次数
socket: "",
uri: "",
lockReconnect: false,
timer: null,
heartbeat: null,
heartbeatTimeOut: null,
};
},
computed: {
...mapGetters(["userInfo"]),
},
beforeDestroy () {
this.destroyedWs();
},
methods: {
destroyedWs () {
console.log("ws销毁");
// 关闭使用close方法关闭socket
if (this.socket) {
this.socket.close();
}
this.socket = null;
// 清除定时器
this.timer = null;
clearInterval(this.timer);
clearTimeout(this.heartbeat);
this.heartbeat = null;
clearTimeout(this.heartbeatTimeOut);
this.heartbeatTimeOut = null;
},
//初始化方法
init () {
this.initWebSocket();
},
// 初始化WebSocket
initWebSocket () {
if (typeof WebSocket === "undefined") {
alert("您的浏览器不支持socket");
} else {
const uri =
"ws://" +
"192.168.0.114:8686" +
"/mqtt-print/imserver/" +
this.userInfo.userId;
// 实例化socket
this.socket = new WebSocket(uri);
// 监听socket连接
this.socket.onopen = this.open;
// 监听socket错误信息
this.socket.onerror = this.error;
// 监听socket消息
this.socket.onmessage = this.getMessage;
// 连接关闭
this.socket.onclose = this.close;
}
},
open: function () {
console.log("socket连接成功");
//开启心跳
this.startHeartbeat();
},
error: function () {
console.log("连接错误");
//重连
this.reconnect();
},
getMessage: function (msg) {
const text = msg.data;
//收到服务器信息,心跳重置并发送
this.startHeartbeat();
if (text.indexOf("ping") > 0) {
return;
}
this.$emit("getMessage", text);
},
send: function (params) {
this.socket.send(params);
},
close: function () {
console.log("socket已经关闭");
},
/**
* 重新连接(无限重连)
*/
reconnect () {
if (this.socket.readyState === 1) {
// 如果状态等于1代表 websocket连接正常
return;
}
if (
this.lockReconnect ||
(this.maxReconnect !== -1 && this.reconnectTime >= this.maxReconnect)
) {
return;
}
// 让重连锁变为true,阻止进入下一个循环
this.lockReconnect = true;
setTimeout(() => {
this.reconnectTime++;
console.log("尝试重连");
// 建立新连接
this.initWebSocket();
this.lockReconnect = false;
}, 5000);
},
/**
* 开启心跳
*/
startHeartbeat () {
const webSocket = this.socket;
// 清空定时器
clearTimeout(this.heartbeat);
this.heartbeat = null;
clearTimeout(this.heartbeatTimeOut);
this.heartbeatTimeOut = null;
// 延时发送下一次心跳
// console.log("心跳开启");
this.heartbeat = setTimeout(() => {
// 如果连接正常
// console.log("连接状态", webSocket.readyState);
if (webSocket.readyState === 1) {
//这里发送一个心跳,后端收到后,返回一个心跳消息,
let params = JSON.stringify({
type: "ping",
toUserId: this.userInfo.userId,
});
webSocket.send(params);
// 心跳发送后,如果服务器超时未响应则断开,如果响应了会被重置心跳定时器
this.heartbeatTimeOut = setTimeout(() => {
webSocket.close();
// 响应超时时间
}, 10 * 1000);
} else {
// 否则重连
this.reconnect();
}
// 心跳间隔时间是30s
}, 30 * 1000);
},
},
};
</script>