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>

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

  • 相关阅读:
    springboot文件上传: 单个文件上传 和 多个文件上传
    Eclipse:很不错的插件-devStyle,将你的eclipse变成idea风格
    springboot项目搭建:结构和入门程序
    POJ 3169 Layout 差分约束系统
    POJ 3723 Conscription 最小生成树
    POJ 3255 Roadblocks 次短路
    UVA 11367 Full Tank? 最短路
    UVA 10269 Adventure of Super Mario 最短路
    UVA 10603 Fill 最短路
    POJ 2431 Expedition 优先队列
  • 原文地址:https://www.cnblogs.com/fmixue/p/14603412.html
Copyright © 2011-2022 走看看