Open ivan135 opened 4 years ago
在项目需要在局域网中,电脑网页和电话实时连接,当收到订单时,网页会有提示
假如使用setInterval轮询接口,需要客户端定时向服务器发送ajax请求,服务器接到请求后返回响应信息。这就需要大量的占据服务器资源。同时在HTTP1.x协议中也存在一些比如线头阻塞、头部冗余等问题
而使用websocket的话,建立在 TCP 协议之上,数据格式比较轻量,性能开销小,通信高效,可以发送文本,也可以发送二进制数据。同时它还没有同源限制,客户端可以与任意服务器通信。
在某些场景下使用websocket的时候,如果设备网络断开,不会立刻触发websocket的任何事件,前端也就无法得知当前连接是否已经断开。这个时候如果调用websocket.send方法,浏览器才会发现链接断开了,便会立刻或者一定短时间后,触发onclose函数。
后端websocket服务也可能出现异常,造成连接断开,这时前端也并没有收到断开通知,因此需要前端定时发送心跳消息ping,后端收到ping类型的消息,立马返回pong消息,告知前端连接正常。如果一定时间没收到pong消息,就说明连接不正常,前端便会执行重连。
为了解决以上两个问题,以前端作为主动方,定时发送ping消息,用于检测网络和前后端连接问题。一旦发现异常,前端持续执行重连逻辑,直到重连成功。
export default { data() { return { websock: null,//建立的连接 lockReconnect: false,//是否真正建立连接 timeout: 30*1000,//30秒一次心跳 timeoutObj: null,//心跳心跳倒计时 serverTimeoutObj: null,//心跳倒计时 timeoutnum: null,//断开 重连倒计时 }; }, created() { //页面刚进入时初始化长连接 this.initWebSocket(); }, destroyed: function() { //页面销毁时关闭长连接 this.websocketclose(); }, methods: { initWebSocket(){//建立连接 //初始化weosocket //const wsuri = "ws://sms.填写您的地址.com/websocket/" //ws地址 const wsuri = "" //建立连接 this.websock = new WebSocket(wsuri); //连接成功 this.websock.onopen = this.websocketonopen; //连接错误 this.websock.onerror = this.websocketonerror; //接收信息 this.websock.onmessage = this.websocketonmessage; //连接关闭 this.websock.onclose = this.websocketclose; }, reconnect() {//重新连接 var that = this; if(that.lockReconnect) { return; }; that.lockReconnect = true; //没连接上会一直重连,设置延迟避免请求过多 that.timeoutnum && clearTimeout(that.timeoutnum); that.timeoutnum = setTimeout(function () { //新连接 that.initWebSocket(); that.lockReconnect = false; },5000); }, heartCheckReset(){//重置心跳 var that = this; //清除时间 clearTimeout(that.timeoutObj); clearTimeout(that.serverTimeoutObj); //重启心跳 that.heartCheckStart(); }, heartCheckStart(){//开启心跳 var self = this; self.timeoutObj && clearTimeout(self.timeoutObj); self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj); self.timeoutObj = setTimeout(function(){ //这里发送一个心跳,后端收到后,返回一个心跳消息, if (self.websock.readyState == 1) {//如果连接正常 self.websock.send("heartCheck"); }else{//否则重连 self.reconnect(); } self.serverTimeoutObj = setTimeout(function() { //超时关闭 self.websock.close(); }, self.timeout); }, self.timeout) }, websocketonopen() {//连接成功事件 //提示成功 s.success("连接成功",3) //开启心跳 this.heartCheckStart(); }, websocketonerror(e) {//连接失败事件 //错误 console.log("WebSocket连接发生错误"); //错误提示 s.error("Websocket error, Check you internet!") //重连 this.reconnect(); }, websocketclose(e) {//连接关闭事件 //关闭 console.log("connection closed (" + e.code + ")"); //提示关闭 s.error("连接已关闭",3); //重连 this.reconnect(); }, websocketonmessage(event) {//接收服务器推送的信息 //打印收到服务器的内容 console.log(event.data); //收到服务器信息,心跳重置 this.heartCheckReset(); }, websocketsend(msg) {//向服务器发送信息 //数据发送 this.websock.send(msg); }, } };
项目的需求
在项目需要在局域网中,电脑网页和电话实时连接,当收到订单时,网页会有提示
选择websocket的原因
假如使用setInterval轮询接口,需要客户端定时向服务器发送ajax请求,服务器接到请求后返回响应信息。这就需要大量的占据服务器资源。同时在HTTP1.x协议中也存在一些比如线头阻塞、头部冗余等问题
而使用websocket的话,建立在 TCP 协议之上,数据格式比较轻量,性能开销小,通信高效,可以发送文本,也可以发送二进制数据。同时它还没有同源限制,客户端可以与任意服务器通信。
websocket使用心跳重连
在某些场景下使用websocket的时候,如果设备网络断开,不会立刻触发websocket的任何事件,前端也就无法得知当前连接是否已经断开。这个时候如果调用websocket.send方法,浏览器才会发现链接断开了,便会立刻或者一定短时间后,触发onclose函数。
后端websocket服务也可能出现异常,造成连接断开,这时前端也并没有收到断开通知,因此需要前端定时发送心跳消息ping,后端收到ping类型的消息,立马返回pong消息,告知前端连接正常。如果一定时间没收到pong消息,就说明连接不正常,前端便会执行重连。
为了解决以上两个问题,以前端作为主动方,定时发送ping消息,用于检测网络和前后端连接问题。一旦发现异常,前端持续执行重连逻辑,直到重连成功。
代码实现