前言
总计记录一下websocket相关的知识
websocket基本概念
WebSocket 是一种基于 TCP 协议的双向通信协议,它允许在客户端和服务器之间建立持久性的连接,实现实时的双向数据传输。与传统的 HTTP 请求-响应模式不同,WebSocket 提供了一种全双工通信的方式,使得服务器可以主动向客户端推送数据,而不需要客户端发起请求。
以下是 WebSocket 的一些基本概念:
-
握手(Handshake):WebSocket 握手是在客户端和服务器之间建立连接的过程。客户端发送一个特殊的 HTTP 请求,称为握手请求,服务器返回一个特殊的 HTTP 响应,称为握手响应。握手成功后,客户端和服务器之间的连接就建立起来了。
-
持久连接(Persistent Connection):WebSocket 的连接是持久性的,即一旦建立连接,它会一直保持打开状态,直到客户端或服务器主动关闭连接。
-
数据帧(Frame):WebSocket 使用数据帧来传输数据。数据帧是 WebSocket 协议中的基本单位,它包含了数据的有效载荷以及一些控制信息,如数据类型、数据长度等。
-
双向通信(Bidirectional Communication):WebSocket 允许客户端和服务器之间进行双向通信,即双方都可以发送和接收数据。这使得实时的双向数据传输成为可能,例如实时聊天、实时数据更新等。
-
协议升级(Protocol Upgrade):WebSocket 使用 HTTP 协议进行握手,然后通过协议升级将连接升级为 WebSocket 连接。协议升级后,客户端和服务器之间的通信就不再使用 HTTP,而是使用 WebSocket 协议
websocket适用场景
-
实时通信:WebSocket 可以实现实时的双向数据传输,适用于实时通信场景,例如在线聊天、实时游戏等。(最为常用,同一时间操作不同数据的同步)
-
实时数据更新:WebSocket 可以实现服务器向客户端推送实时数据更新,适用于需要实时更新数据的场景,例如股票行情、天气预报等。(项目中多用于感知到不同用户的操作,)
-
大规模数据传输:WebSocket 可以实现高并发、低延迟的数据传输,适用于需要传输大规模数据的场景,例如视频直播、音频流传输等。(推流操作流,笔者多接触与云桌面,利用视频流模拟操作系统)
-
WebRTC:WebSocket 可以作为 WebRTC 技术的信令通道,用于建立点对点的实时通信连接。(特定领域,例如笔者曾参与开发j方的某作战平台)
websocket的优点
低延迟、高并发、实时性强
websocket的实现
简单封装一个websocket,代码贴在下面了
class webSocketClass {
constructor(thatVue) {
this.lockReconnect = false;
this.localUrl = process.env.NODE_ENV === 'production' ? '你的websocket生产地址' : '测试地址'
this.globalCallback = null;
this.userClose = false;
this.createWebSocket();
this.webSocketState = false
this.thatVue = thatVue
}
createWebSocket() {
let that = this;
// console.log('开始创建websocket新的实例', new Date().toLocaleString())
if (typeof (WebSocket) != "function") {
alert("您的浏览器不支持Websocket通信协议,请更换浏览器为Chrome或者Firefox再次使用!")
}
try {
that.ws = new WebSocket(that.localUrl);
that.initEventHandle();
that.startHeartBeat()
} catch (e) {
that.reconnect();
}
}
//初始化
initEventHandle() {
let that = this;
// //连接成功建立后响应
that.ws.onopen = function () {
console.log("连接成功");
};
//连接关闭后响应
that.ws.onclose = function () {
// console.log('websocket连接断开', new Date().toLocaleString())
if (!that.userClose) {
that.reconnect(); //重连
}
};
that.ws.onerror = function () {
// console.log('websocket连接发生错误', new Date().toLocaleString())
if (!that.userClose) {
that.reconnect(); //重连
}
};
that.ws.onmessage = function (event) {
that.getWebSocketMsg(that.globalCallback);
// console.log('socket server return '+ event.data);
};
}
startHeartBeat() {
// console.log('心跳开始建立', new Date().toLocaleString())
setTimeout(() => {
let params = {
request: 'ping',
}
this.webSocketSendMsg(JSON.stringify(params))
this.waitingServer()
}, 30000)
}
//延时等待服务端响应,通过webSocketState判断是否连线成功
waitingServer() {
this.webSocketState = false//在线状态
setTimeout(() => {
if (this.webSocketState) {
this.startHeartBeat()
return
}
// console.log('心跳无响应,已断线', new Date().toLocaleString())
try {
this.closeSocket()
} catch (e) {
console.log('连接已关闭,无需关闭', new Date().toLocaleString())
}
this.reconnect()
//重连操作
}, 5000)
}
reconnect() {
let that = this;
if (that.lockReconnect) return;
that.lockReconnect = true; //没连接上会一直重连,设置延迟避免请求过多
setTimeout(function () {
that.createWebSocket();
that.thatVue.openSuccess(that) //重连之后做一些事情
that.thatVue.getSocketMsg(that)
that.lockReconnect = false;
}, 15000);
}
webSocketSendMsg(msg) {
this.ws.send(msg);
}
getWebSocketMsg(callback) {
this.ws.onmessage = ev => {
callback && callback(ev);
};
}
onopenSuccess(callback) {
this.ws.onopen = () => {
// console.log("连接成功", new Date().toLocaleString())
callback && callback()
}
}
closeSocket() {
let that = this;
if (that.ws) {
that.userClose = true;
that.ws.close();
}
}
}
export default webSocketClass;