一、什么是WebScoket
- WebScoket是HTML5下的一种新的协议,是建立在TCP协议之上的
- WebScoket并不是全新的协议,在握手阶段是利用HTTP协议完成的,当握手结束后,便可以双向数据传输了
二、WebScoket的特点
- 建立在TCP协议之上
- 与HTTP协议有很好的兼容性,默认端口也是80和443,握手阶段采用HTTP协议,因此握手阶段也不容易被屏蔽,能通过各种HTTP的代理服务器。
- 数据格式比较轻量,性能开销小,通信高效。
- 可以发送文本也可以发送二进制数据
- 没有同源限制,客户端可以与任意服务器通信。
- 协议标识是ws(加密wss),服务器网址就是url
三、使用WebScoket
webscoket的方法与属性
- Socket.readyState: 只读属性readyState表示连接状态
0-连接尚未建立
1-连接已建立,可以进行通信
2-连接正在关闭
3-连接已经关闭或连接不能打开
1.创建实例
2.发送消息
3.接收消息
4.关闭连接
- Socket.bufferedAmount:只读属性bufferedAmount已被send()放入队列中等待传输,但是还没有发出UTF-8文本字节数,也可以根据此属性判断webscoket数据是否发送完成。
- Socket.onopen:连接建立
- Socket.onmessage:客户端接收服务端数据
- Socket.onerror:通信发送错误
- Socket.onclose:连接关闭
创建WebSocket
let Socket = new WebSocket(url, [protocol])
// url: ws://xxx
// protocol:可接受的自协议
发送消息
Socket.onopen = () => {
let param = {
data: '数据测试'
};
Socket.send(JSON.stringify(parmas))
}
接收消息
Socket.onmessage = (e) => {
console.log(e.data);
}
关闭连接
Scoket.onerror = () => {}
Scoket.onclose = () => {}
四、断线重连
当websocket在数据传输过程中,如果长时间没有发送数据可能会出现连接断开的情况,此时onclose()是不会触发的,所以我们需要做心跳检测,避免出现断开的情况
websocketUtil
const websocketUrl = 'xxx';
class WebSocketUtil {
constructor(wsPath){
let protocol = (window.location.url === 'https:') ? 'wss://' : 'ws://';
let url = protocol + websocketUrl;
this.websock = new WebSocketUtil(url);
}
// 心跳检测
heartCheck(){
let self = this;
if (this.timeoutObj) {
clearInterval(this.timeoutObj)
}
this.timeoutObj = setInterval(function(){
// 这里发送一个心跳,后端收到后,返回一个心跳消息,
// onmessage拿到返回的心跳就说明连接正常
if (self.readyState() != 1) {
clearInterval(self.timeoutObj)
}
self.websock.send("HeartBeat");
// 发送心跳检测
console.log("HeartBeat");
}, 5000)
}
// 实例创建后自定义创建 handler
on(funName,handler){
this.websock[`on${funName}`] = handler
// 暴露onmessage、onclose、onopen、onerror方法
}
// 发送scoket数据
send(msg){
this.websock.send(msg)
}
// 监听websock链接状态
readyState(){
// 获取webscoket实例链接状态 0:正在建立连接连接,还没有完成 1:连接成功,可以进行通信 2:连接正在进行关闭握手,即将关闭 3:连接已经关闭或者根本没有建立
return this.websock.readyState;
}
}
// 导出实例
export default WebSocketUtil
实例创建
// index.vue
import $WebSocketUtil from '../../api/scoket.js'
// 实例化聊天scoket
initScoket() {
let token = this.$cookies.get('token')
let pathData = '/chat?token=' + token
this.webscoketChat = new $WebSocketUtil(pathData)
this.webscoketChat.on('message', this.websocketonmessage)
this.webscoketChat.on('open', this.websocketonpen)
this.webscoketChat.on('error', this.websocketonerror)
this.webscoketChat.on('close', this.websocketonerror)
Vue.prototype.$scoketChat = this.webscoketChat
},
// socket建立成功后开始进行心跳检测
websocketonpen() {
this.webscoketChat.heartCheck()
},
// 发生错误断线重连
websocketonerror() {
let self = this
if (this.reconnectChat) { return }
this.reconnectChat = true
setTimeout(function () {
self.initScoket()
console.log("Chat正在重连...")
self.reconnectChat = false
}, 10000)
},
// 接收 webscoket 消息
websocketonmessage(e) {
let res = JSON.parse(e.data);
HandleChat(res.type,res.data,res.wxId || '');
},