websocket简介(可跳过)
websocket是一种全双工通信长链接,大多用来实现及时通讯,数据实时性要求较为高的地方,在websoket未出现的时候前端使用的setInterval轮训进行数据更新的,在那些对于数据实时性要求不高地方我们仍可以使用 轮训。
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)通常的协议标示符号为http,而websoket是ws(默认端口80),加密通信为wss(默认端口443)对应为https
Http-长短链接
HTTP连接分为长连接和短连接,而我们现在常用的都是HTTP1.1,因此我们用的都是长连接。这句话其实只对了一半,我们现如今的HTTP协议,大部分都是1.1的,因此我们平时用的基本上都是长连接。HTTP协议根本没有长短连接这一说。HTTP协议是基于请求/响应模式的,因此只要服务端给了响应,本次HTTP连接就结束了,或者更准确的说,是本次HTTP请求就结束了,根本没有长短连接这一说,
TCP-长短链接
长连接和短连接,其实是说的TCP连接。TCP连接是一个双向的通道,它是可以保持一段时间不关闭的,因此TCP连接才有真正的长连接和短连接。HTTP协议说到底是应用层的协议,而TCP才是真正的传输层协议,只有负责传输的这一层才需要建立连接。
就像快递 填的快递地址单号是http,而运输工具例如车 对应的是tcp
websocket 心跳机制/断线重连机制
当双方通讯都已经链接,如果没有外在原因,双方不断开链接本质上链接不会中断。
但是存在的外在因素会让websoket中断例如:(网络断线,网络状态不佳,链接需要在内网而内网无法联机,链接的进程被杀死/服务器长时间无通讯)
为了保证这个通信一直保持鲜活 我们需要增加 心跳机制/断线重连机制
心跳机制
在与服务器建立起链接的时候(open) 开始心跳
每隔30s(或者指定时间 这里都暂用30s)向服务器 send 一条心跳消息 ⌛等待 服务器给 答复
如果在指定30s 前端收到服务器返回的消息(message), 重置心跳 重新开始计时30s 再次心跳。
如果没有收到消息(可能是网络等原因) 服务器无应答 调用websocke.close() 关闭这个长链接 再重新发送新链接请求 请求重新连接 服务器
重连机制
我们分别在 websokcet 报错/close/errno/无响应(这里心跳直接调用close,再用close进行重新连接)
封装 具体代码
调用方法
import { socketContact } from '@/utils/websocket'
const wss = socketContact('/ws/quality_panel/', 'quality panel data', (data) => {
tableData.value = data // 可以自定义数据处理
})
具体封装代码:
const socketContact = function (contactUrl = '', getDataSecret = '', getDataFn = () => {}) {
const baseUrl = process.env.VUE_APP_API_WEBSOCKET_URL // baseURL
const callBack = getDataFn // callback返回数据函数
const url = contactUrl // 后缀url
// getDataSecret 需要发送给服务器的数据
let socket // websocket本体
let lock = false // 避免重复连接
let replyOverTime = null // 服务器回复超时setTimeout
let hearByteTime = null // 心跳 setTimeout
try {
socket = new WebSocket(baseUrl + url)
socket.addEventListener('open', function (event) {
socket.send(getDataSecret)
heatByte() // 开始心跳
console.log('链接成功', contactUrl, getDataSecret)
})
socket.addEventListener('message', function (event) {
resetHardByte() // 重置心跳
// 这里transporting...' 和'invalid command...'为服务器心跳回复 不做数据返回处理
if (event.data === 'transporting...' || event.data === 'invalid command...') return
// 处理服务器返回数据 这里可自定义
const str = event.data.replaceAll('None', 'null')
// eslint-disable-next-line no-eval
const data = eval('(' + str + ')')
callBack(data)
});
socket.addEventListener('close', function (event) {
console.log('链接关闭', event.code)
reconnect(url, getDataSecret, callBack) // 尝试重新连接
});
socket.addEventListener('errno', function (event) {
console.log('链接报错')
reconnect(url, getDataSecret, callBack)// 尝试重新连接
});
} catch (e) {
console.log('catch', e)
reconnect(url, getDataSecret, callBack) // 尝试重新连接
}
function heatByte (type) {
hearByteTime && clearInterval(hearByteTime)
replyOverTime && clearInterval(replyOverTime)
// 每30s一次心跳
hearByteTime = setTimeout(() => {
if (socket.readyState === 1) {
socket.send('heart byte') // 没问题进行心跳
console.log('heart byte')
}
// 重新链接超时 60s无回复 关闭连接 尝试重新链接
replyOverTime = setTimeout(() => {
socket.close()
console.log('网络/其他问题 回复超时间关闭')
}, 60000)
}, 30000)
}
function resetHardByte () {
// 进行下一次心跳
hearByteTime && clearTimeout(hearByteTime)
replyOverTime && clearTimeout(replyOverTime)
heatByte()
}
function reconnect (url, getDataSecret, callBack) {
if (lock) return
lock = true
setTimeout(() => {
lock = false
socketContact(url, getDataSecret, callBack)
console.log('正在尝试重新连接')
}, 5000)
}
return socket
}
export { socketContact }
参考
长链接短连接:http://t.csdn.cn/Ne7g3
websokcet 阮一峰:https://www.ruanyifeng.com/blog/2017/05/websocket.html文章来源:https://www.toymoban.com/news/detail-501434.html
websokcet:http://t.csdn.cn/j42h5文章来源地址https://www.toymoban.com/news/detail-501434.html
到了这里,关于websocket前端封装代码,心跳机制断线重连的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!