WebSocket 是什么?
WebSocket 是基于 TCP 的一种新的应用层网络协议。它实现了浏览器与服务器全双工通信,即允许服务器主动发送信息给客户端。因此,在 WebSocket 中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变得更加简单。
WebSocket 的特点
- 建立在 TCP 协议之上;
- 与 HTTP 协议有着良好的兼容性:默认端口也是 80(ws) 和 443(wss,运行在 TLS 之上),并且握手阶段采用 HTTP 协议;
- 较少的控制开销:连接创建后,ws 客户端、服务端进行数据交换时,协议控制的数据包头部较小,而 HTTP 协议每次通信都需要携带完整的头部;
- 可以发送文本,也可以发送二进制数据;
- 没有同源限制,客户端可以与任意服务器通信;
- 协议标识符是 ws(如果加密,则为 wss),服务器网址就是 URL;
- 支持扩展:ws 协议定义了扩展,用户可以扩展协议,或者实现自定义的子协议(比如支持自定义压缩算法等);
WebSocket 使用(心跳机制)
<script>
export default {
data() {
return {
socket: null,
aliveTime: new Date().getTime(),
checkTimer: null
}
},
computed: {
token() {
return this.$store.getters.token
}
},
beforeDestroy() {
clearInterval(this.checkTimer)
this.socket && this.socket.close()
},
mounted() {
if (this.socket && this.socket.readyState === 1) {
clearInterval(this.checkTimer)
this.socket.close()
}
if (this.socket && this.socket.readyState === 3) {
this.initWebSocket()
}
this.getData()
},
methods: {
getData() {
// ......
this.initWebSocket()
},
initWebSocket() {
if (typeof WebSocket === 'undefined') {
this.$message({ message: '您的浏览器不支持WebSocket' })
return false
}
this.checkTimer && clearInterval(this.checkTimer)
this.socket && this.socket.close()
this.aliveTime = new Date().getTime()
const token = this.token.split('Bearer ')[1]
const wsurl = `wss://${process.env.VUE_APP_DOMAIN}/ws?token=${token}`
this.socket = new WebSocket(wsurl)
this.socket.onmessage = this.websocketonmessage
this.socket.onerror = this.websocketonerror
this.checkTimer = setInterval(this.checkWebsocketAlive, 5 * 1000)
},
websocketonmessage(e) {
const response = JSON.parse(e.data)
if (response.message === 'success') {
const data = response.data
// 处理 data
}
// 这里的场景是服务端主动推数据,接收到消息说明连接正常
if (response.message === 'connection alive') {
this.aliveTime = new Date().getTime()
}
},
websocketonerror() {
clearInterval(this.checkTimer)
this.socket.close()
},
checkWebsocketAlive() {
const now = new Date().getTime()
if (now - this.aliveTime > 60 * 1000) {
this.aliveTime = now
this.initWebSocket()
}
},
}
}
</script>