websocket基础与心跳模式
·
什么是websocket?
websocket,是web浏览器与web服务器之间全双工通信标准。它可以在用户的浏览器和服务器之间打开交互式通信会话。使用此 API,可以向服务器发送消息并接收事件驱动的响应,而无需通过轮询服务器的方式以获得响应。
个人理解
1、http是浏览器主动的去进行连接,由服务器主动断开且只进行一次连接。
2、websocket是服务器或浏览器主动进行连接,断开连接是需要浏览器或服务器主动的断开,解决了http请求的单向连接,所以说websocket是双方各自进行断开或连接。
websocket简单示例
websocket的基础在这里不做过多阐述,详情可参考MDN对websocket的解释websocket
// 创建一个websocket连接.
const socket = new WebSocket('ws://localhost:8080');
// 监听连接成功
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
// 监听返回的数据
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
});
什么是
websocket的心跳模式?
在进行开发的时候我们可能只是简单的运用websocket,但是有没有想过如果在进行连接的时候连接失败,如何判断是服务器主动断开连接还是请求连接失败呢?如果请求连接失败我们就断开连接吗?这是错的,我们应该去进行重连,在连接的时候加入判断如果服务器主动断开,我们关闭websocket连接,否则我们进行重连,设置一个定时重连,直到我们可以连接到服务器为止,这样做的话,不论是什么情况的断开连接我们都可以一一进行解决。
心跳模式的实现
var socket = null // 申明socket,创建他的实例
var timeout = 1000 * 60; // 后端推送间隔为两分钟(待定)
var reconnectTimeout = 1000 * 60 * 2; // 尝试重连间隔为两分钟
var wsMap = new Map(); // ws 对象的集合库
/**
* 初始化 props ,记录构建 socket 所提供的的信息,把成员挂载到 socket 的实例对象上
* @param {*} socket 传入的 socket 实例
* @param {*} onMessageCallback 收到数据时的回调函数,将数据传送给要接受的那个函数做处理
* @param {*} wsKey 对应 socket 唯一的 key,指定唯一的访问地址
*/
function initProps(socket, onMessageCallback, wsKey) {
console.log("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
console.log(wsKey, socket);
socket.onMessageCallback = onMessageCallback
socket.wsKey = wsKey
socket.timeout = null // 心跳定时器
socket.serverTimeout = null // 心跳反馈定时器
// 这里保存上一个 ws 的重连状态,配合 reconnect 的节流功能,保存不会频繁发送无意义的心跳
socket.debounceTimeout = wsMap.get(wsKey) ? wsMap.get(wsKey).debounceTimeout : null;
wsMap.set(wsKey, socket); // 保存或者更新 ws 在资料库 map 的数据
}
/**
* 开启心跳模式
* @param {*} ws 传入的 socket 实例
*/
function start(ws) {
ws.timeout = setTimeout(() => {
// ws.send(JSON.stringify({type: 1000, data: 'HeartBeat'}))
console.log("执行到这里了,start22222");
ws.serverTimeout = setTimeout(() => {
console.log("没有返回直接关闭");
ws.close() // timeout 时间后没有返回,直接关闭此次连接
}, timeout)
}, timeout)
}
/**
* 重连操作
*/
function reconnect(ws) {
// 节流
clearTime(ws); // 如果发起重连,则关闭心跳等定时器
const callNow = !ws.debounceTimeout;
ws.debounceTimeout = setTimeout(() => {
ws.debounceTimeout = null;
reconnect(ws); // 已进行过重连的,下一次必须经过 reconnectTimeout 之后才能再次发起重连
}, reconnectTimeout);
if (callNow) {
console.log("来到这里执行");
initWebSocket(ws.url, ws.onMessageCallback, ws.wsKey);
}
}
/**
* 清除定时器
*/
function clearTime(ws) {
console.log(ws);
ws.timeout && clearTimeout(ws.timeout)
ws.serverTimeout && clearTimeout(ws.serverTimeout)
ws.debounceTimeout && clearTimeout(ws.debounceTimeout)
}
/**
* 重置心跳
*/
function reset(ws) {
clearTime(ws)
start(ws)
}
/**
* 获取本地地址,代理的时候有用
* @returns 本地的地址
*/
function getWebIP() {
const curIP = window.location.host;
return curIP;
}
/**
* 收到服务器数据后的回调函数
* @param {*} event websocket 发送来的数据
* @param {*} onMessageCallback 收到数据时的回调函数,将数据传送给要接受的那个函数做处理
*/
function onMessage(event, onMessageCallback) {
// 重置心跳
reset(event.currentTarget)
if(onMessageCallback) {
try {
let res = JSON.parse(event.data)
// if(res.data.text === 'alive') { // 与后端约定,心跳反馈标识为: alive,得到 alive 标识链接正常,什么也不做(待定)
// console.log("websocket接收信息")
// console.log(res);
// onMessageCallback(res)
// return
// }
console.log("websocket接收信息")
console.log(res);
onMessageCallback(res)
} catch (error) {
onMessageCallback(null)
}
}
}
/**
* 连接成功后的回调函数
*/
function onOpen() {
// 开启心跳
start(this)
console.log("websocket连接成功")
}
/**
* 连接关闭后的回调函数
*/
function onclose(event) {
if(event.code !== 1000) { // 不是手动关闭的话,进行重连
console.log("wensocket非人为关闭关闭");
reconnect(this)
}else {
// 主动关闭,不再重连
console.log(this);
clearTime(this)
console.log(wsMap);
// 删除 wsMap 中的数据
wsMap.delete(this.wsKey)
console.log(wsMap);
console.log("wensocket连接关闭");
}
}
/**
* 报错时的回调函数
*/
function onError() {
console.log("websocket建立连接失败");
}
/**
* 初始化 websocket
*/
function initWebSocket(
url,
onMessageCallback,
wsKey // 对应 socket 唯一的 key,为了指定唯一的访问地址
) {
const wsurl = url.includes("ws://") ? url : "ws://" + getWebIP() + url
socket = new WebSocket(wsurl)
socket.onmessage = (event) => {
onMessage(event, onMessageCallback)
}
socket.onopen = onOpen
socket.onerror = onError
socket.onclose = onclose
// 初始化 props ,记录构建 socket 所提供的的信息
initProps(socket, onMessageCallback, wsKey)
}
/**
* 关闭 websocket 连接的方法
*/
function wesocketClose() {
socket.close()
}
export {
initWebSocket,
wesocketClose
}
websocket的使用

vue.config.js中的代理配置

更多推荐



所有评论(0)