zoukankan      html  css  js  c++  java
  • websocket 心跳及重连

    最近被问到一个项目中比较常见的问题,因为之前自己只是用过,但并未真正了解具体是怎么实现的,所以今天抽时间整理了下,避免下次再掉坑中。。

    一般toB的项目中,如果有实时通信的需求,目前较为广泛的都会采用websocket来实现客户端与服务端的双向通信,其实主要原理是客户端定时向服务端发送消息,如果在规定时间内,收到服务端推送回的消息,则说明通信正常,否则就挂掉了,及时关闭连接;

    今天简单封装了下,websocket中的心跳重连,主要代码如下:

    class HeartSocket {
    
        constructor(options) {
            this.url = options.url; //请求路径
            this.timeout = options.timeout;//心跳超时时间 毫秒
            this.isHeart = options.isHeart;//是否开启心跳
            this.isReconnection = options.isReconnection; //是否断开重连
            this.ws = null; ///WebSocket的引用
            this.status = null;//记录状态
            this.lockReconnect = false,//避免重复连接
            this.timeoutObj = null;//模拟延时器1
            this.serverTimeoutObj = null;//模拟延时器2
        }
    
        reConnection() {
            if (this.lockReconnect) return;
            this.lockReconnect = true;
            //判断当前浏览器是否支持WebSocket
            if ('WebSocket' in window) {
                this.ws = new WebSocket(this.url);
            } else {
                alert('Not support websocket')
            }
    
            //打开连接
            this.ws.onopen = (e) => {
                this.status = 'open';
                console.log('socket连接成功', e)
                if (this.isHeart) this.heartCheck();
            }
    
            //消息交互
            this.ws.onmessage = (e) => {
                console.log('后台接收到前台传值,还有心跳...');
                //心跳检测重置
                this.heartCheck();
            }
    
            //关闭连接
            this.ws.onclose = (e) => {
                console.log('关闭连接', e);
                this.closeSocket(e);
            }
    
            //报错
            this.ws.onerror = (e) => {
                console.log('error', e);
                this.closeSocket(e);
            }
        }
    
        resetHeart() {
            this.timeoutObj && clearTimeout(this.timeoutObj);
            this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
        }
    
        heartCheck() {
            console.log('开始测试心跳');
            this.timeoutObj = setTimeout(() => {
                //这里发送一个心跳,后端收到后,返回一个心跳消息,
                console.log('发送消息,测试后台是否运行中...');
                //任意发一个消息过去,后台接收,如果在onmessage收到消息,说明后台没有挂掉,有心跳
                this.ws.send("666");
                this.serverTimeoutObj = setTimeout(() => {
                    console.log("后台挂掉,没有心跳了....");
                    console.log("打印websocket的地址:" + this.url);
                    this.ws.close();
                    // createWebSocket();
                }, this.timeout);
                this.lockReconnect = false;
            }, this.timeout);
        }
    
        closeSocket(e) {
            this.resetHeart();
            if (this.status !== 'close') {
                console.log('断开,重连', e)
                if (this.isReconnection) {
                    console.log("正在重连,当前时间" + new Date())
                    //重连
                    this.reConnection();
                }
            } else {
                //手动关闭
                console.log('手动关闭', e)
            }
        }
    
        close() {
            this.status = 'close';
            this.resetHeart();
            return this.ws.close();
        }
    
        sendMsg(data) {
            let msg = JSON.stringify(data);
            return this.ws.send(msg)
        }
    
    }

    调用如下:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>websocket心跳重连</title>
    </head>
    
    <body>
        <div>
            <input type="text" placeholder="请输入路径" value="ws://172.16.253.166:48081/websocket" id="url">
            <button onclick="concat()"> concat </button>
            <button onclick="closeWebSocket()"> close </button>
        </div>
        <script src="./index.js"></script>
        <script>
    
            let url = document.getElementById('url').value;
    
            const ws = new HeartSocket({
                url: url,
                isHeart: true, //是否心跳
                timeout: 10000,// 心跳间隔时间
                isReconnection: true, //是否断开后自动重连
            })
    
            function concat() {
                //判断客户端是否联网
                // if (navigator.onLine) {
                //     console.log('网络已连接');
                // } else {
                //     console.log('已断网');
                // }
                ws.reConnection();
            }
    
            // 发送消息
            //ws.sendMsg(message);
    
            //关闭连接
            function closeWebSocket() {
                if (ws) ws.close();
            }
    
            //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
            window.onbeforeunload = function () {
                ws.close();
            }
    
        </script>
    </body>
    
    </html>

    如有问题,还请及时指正,蟹蟹~

  • 相关阅读:
    字符串----不可重叠的最长重复子串
    字符串----最长重复子串
    字符串----HDU-1358
    字符串----hiho字符串(尺取法)
    字符串匹配(二)----KMP算法
    字符串匹配(一)----Rabin-Karp算法
    字符串----最短摘要生成(尺取法)
    【Hibernate 检索策略】
    【Hibernate 多表查询】
    【Hibernate QBC】
  • 原文地址:https://www.cnblogs.com/fmixue/p/14603412.html
Copyright © 2011-2022 走看看