笔记之websocket

147 阅读2分钟

mdn

初识websocket

1.客户端

const CLOSE_TYPE_RECONNECT = 'reconnect';
class WebSocketPrivate {
    constructor (props) {
        let { url, autoReconnect = true, onerrAutoReconnect = true, onerror, isActiveHeart = true, heartMsg = 'HeartBeat', receiveMessage, connectTime = 5000 } = props;
        // 基础属性
        this.ws = null;
        this.url = url;
        // 接受信息的 函数
        this.receiveMessage = receiveMessage;
        // 是否开启心跳检测:默认开启
        this.isActiveHeart = isActiveHeart;
        this.heartMsg = heartMsg;
        // 断线是否自动重连,默认 是
        this.autoReconnect = autoReconnect;
        // 连接错误时 是否重连 默认 是
        this.onerrAutoReconnect = onerrAutoReconnect;
        this.onerror = onerror;
        // 重连机制
        this.lockReconnect = false;
        this.tt = null;

        const _this = this;
         /**
         * websocket心跳检测
         */
        this.heartCheck = {
            timeout: connectTime,
            timeoutObj: null,
            serverTimeoutObj: null,
            reset: function () {
                clearTimeout(this.timeoutObj);
                clearTimeout(this.serverTimeoutObj);
                return this;
            },
            start: function () {
                var self = this;
                this.timeoutObj && clearTimeout(this.timeoutObj);
                this.serverTimeoutObj && clearTimeout(this.serverTimeoutObj);
                this.timeoutObj = setTimeout(function () {
                    //这里发送一个心跳,后端收到后,返回一个心跳消息,
                    //onmessage拿到返回的心跳就说明连接正常
                    _this.send(_this.heartMsg);
                    console.log('ping');
                    self.serverTimeoutObj = setTimeout(function () { // 如果超过一定时间还没重置,说明后端主动断开了
                        console.log('关闭服务');
                        _this.autoReconnect ? _this.ws.close(3005, CLOSE_TYPE_RECONNECT) : _this.ws.close();//如果onclose会执行reconnect,我们执行 websocket.close()就行了.如果直接执行 reconnect 会触发onclose导致重连两次
                    }, self.timeout)
                }, self.timeout)
            }
        };
    }
    // 创建websocket
    createWebsocket () {
        let { url } = this;
        try {
            if ('WebSocket' in window) {
                this.ws = new WebSocket(url)
            } else if ('MozWebSocket' in window) {
                this.ws = new MozWebSocket(url)
            } else {
                this.ws = new SockJS(url)
                console.warn('浏览器版本暂不支持')
            }
            this.init();
        } catch (err) {
            console.log('catch' + err);
            this.autoReconnect && this.reconnect();
        }
    }

    init () {
        const _this = this;
        //连接成功建立的回调方法
        this.ws.onopen = function (event) {
            console.log("WebSocket:已连接");
            //心跳检测重置
            _this.startHeart();
        };

        //接收到消息的回调方法
        this.ws.onmessage = function (event) {
            console.log("WebSocket:收到一条消息", event.data);
            event.data !== _this.heartMsg && _this.receiveMessage && _this.receiveMessage(event)
            _this.startHeart();
        };

        //连接发生错误的回调方法
        this.ws.onerror = function (event) {
            console.log("WebSocket:发生错误");
            _this.onerror && _this.onerror(event)
            _this.onerrAutoReconnect && _this.reconnect();
        };

        //连接关闭的回调方法
        this.ws.onclose = function (event) {
            let { reason } = event;
            console.log("WebSocket:已关闭");
            _this.stopHeart();//心跳检测
            if (reason === CLOSE_TYPE_RECONNECT) {
                _this.reconnect();
            }
        };

        //监听窗口关闭事件,当窗口关闭时,主动去关闭websocket连接,防止连接还没断开就关闭窗口,server端会抛异常。
        window.onbeforeunload = function () {
            _this.ws.close();
        };
    }

    /**
     * websocket重连
     */
    reconnect() {
        if (this.lockReconnect) {
            return;
        }
        this.lockReconnect = true;
        this.tt && clearTimeout(this.tt);
        this.tt = setTimeout(() => {
            console.log('重连中...');
            this.lockReconnect = false;
            this.createWebsocket();
        }, 4000);
    }

    startHeart () {
        this.isActiveHeart && this.heartCheck.reset().start();
    }

    stopHeart () {
        this.heartCheck.reset()
    }
    //关闭连接
    closeWebSocket () {
        this.ws.close();
    }

    //发送消息
    send (message) {
        this.ws.send(message);
    }

}

export default WebSocketPrivate;

2. 服务端

node 简单写法

var WebSocket = require('ws');

var wss = new WebSocket.Server({ port: 3001 });

wss.on('connection', function connection(ws) {
    console.log('server: receive connection.');
    
    ws.on('message', function incoming(message) {
        console.log('server: received: %s', message);
        ws.send(message);
    });

    ws.send('world');
});