// ////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2016-present // All Rights Reserved. // // Author: AlexWang // Date: 2016-08-27 21:40:49 // Last Modified by: AlexWang // Last Modified time: 2016-12-05 12:02:48 // QQ Email: 1669499355@qq.com // Description: 底层Socket管理器,保持一直在线及异常重连. // // ////////////////////////////////////////////////////////////////////////////// import Emiter from 'Emiter'; import Loger from 'Loger'; let loger = Loger.getLoger('EverSocket'); const MCU_MAX_RECONNECTION = 4;//最多重连次数 class EverSocket extends Emiter { constructor() { super(); this._connected = false; this._lastActiveTime = 0;//最后一次收到消息的时间 this._enableEverSocket = false; this.reConnectionCounter = 0;//重连次数 } begin(ip, port) { this._clearHistory(); loger.log('开始WebSocket应用.'); this._enableEverSocket = true; this.wsURL = 'ws://' + ip + ':' + port; this._newConnection(); } end() { loger.log('停止WebSocket应用.'); this._clear(); } switchSocketIp(ip,port) { if(port){ this.wsURL = 'ws://' + ip + ':' + port; }else { this.wsURL = 'ws://' + ip; } } get connected() { return this._connected; } send(data) { if (this._connected) { if (data) { loger.log('SEND MESSAGE-->byteLength->', data.byteLength); } else { loger.log('SEND MESSAGE---->'); } this.websocket.send(data); } else { loger.warn('WebSocket未建立连接.消息忽略'); } } _setConnected(isConn = true) { this._connected = isConn; if (this._connected) { this._emit(EverSocket.OPEN); } else { this._emit(EverSocket.CLOSED); } } _newConnection() { this.websocket = new WebSocket(this.wsURL); this.websocket.binaryType = 'arraybuffer'; this.websocket.onopen = this._onOpen.bind(this); this.websocket.onclose = this._onClose.bind(this); this.websocket.onerror = this._onError.bind(this); this.websocket.onmessage = this._onMessage.bind(this); } _reConnection() { this._clear(); window.clearTimeout(this.reConnectionTimeout); this.reConnectionCounter++; if (this.reConnectionCounter > MCU_MAX_RECONNECTION) { loger.warn('MCU断线重连->已经达到最大重连次数!'); this._emit(EverSocket.ERROR, EverSocket.ERR_SOCKET_RECONNECT_FAILED); this.reConnectionCounter=0; } this.reConnectionTimeout = window.setTimeout(() => { loger.log('MCU断线重连->', this.reConnectionCounter); window.clearTimeout(this.reConnectionTimeout); this._newConnection(); }, EverSocket.RECONN_INTERVAL); } _clear() { loger.log('WebSocket,Timers销毁'); window.clearInterval(this.pingTimer); window.clearInterval(this.pongTimer); window.clearInterval(this.reConnectionTimeout); this._setConnected(false);//先设置状态 this._enableEverSocket = false; if (this.websocket == null) { loger.log('WebSocket,Timers已经销毁'); return; } this.websocket.onopen = undefined; this.websocket.onclose = undefined; this.websocket.onerror = undefined; this.websocket.onmessage = undefined; try { this.websocket.close(); } catch (e) { loger.log('ignore errors'); } this.websocket = undefined; } _clearHistory(){ loger.log('WebSocket->清除记录'); window.clearInterval(this.pingTimer); window.clearInterval(this.pongTimer); window.clearInterval(this.reConnectionTimeout); //this._setConnected(false);//先设置状态 this._connected = false; this._enableEverSocket = false; if (this.websocket == null) { loger.log('WebSocket->已经销毁'); return; } this.websocket.onopen = undefined; this.websocket.onclose = undefined; this.websocket.onerror = undefined; this.websocket.onmessage = undefined; try { this.websocket.close(); } catch (e) { loger.log('ignore errors'); } this.websocket = undefined; } _onOpen() { loger.log('WebSocket建立成功', this.wsURL); this.reConnectionCounter = 0; //启动心跳,检查socket链接状态 this.pingTimer = window.setInterval(this._sendPingHandler.bind(this), EverSocket.PING_INTERVAL); this.pongTimer = window.setInterval(this._checkPongHandler.bind(this), EverSocket.PONG_INTERVAL); this._setConnected(); } _onClose(closeEvent) { loger.log(`WebSocket连接断开 CODE:${closeEvent.code} REASON:${closeEvent.reason} CLEAN: ${closeEvent.wasClean}`, this.wsURL); this._reConnection(); } _onError() { loger.log('WebSocket错误出现'); this._connected = false; this._reConnection(); } _onMessage(messageEvent) { this._lastActiveTime = Date.now(); const bufferData = messageEvent.data; loger.log('RECEIVE MESSAGE-->byteLength->',bufferData.byteLength); if (bufferData.byteLength > 0) { this._emit(EverSocket.MESSAGE, bufferData); } } _sendPingHandler() { if (this._connected) { this.websocket.send(new ArrayBuffer); } else { this._reConnection(); } } _checkPongHandler() { let pongTime = Date.now(); if (this._lastActiveTime && this._lastActiveTime >= pongTime - EverSocket.PONG_INTERVAL && this._lastActiveTime <= pongTime ) { } else { loger.warn('---服务器PINGPONG超时-----'); this._reConnection(); } } } /*//修改之前的 EverSocket.prototype.PONG_INTERVAL = EverSocket.PONG_INTERVAL = 5000; EverSocket.prototype.PING_INTERVAL = EverSocket.PING_INTERVAL = 3000; EverSocket.prototype.RECONN_INTERVAL = EverSocket.RECONN_INTERVAL = 2000;*/ //20170223-mcu服务端修改了心跳的逻辑,如果客户端30秒没有请求,就会按离开的处理 //目前客户端发送心跳请求的空数据,服务端不会每次都回,暂定为10秒心跳一次 EverSocket.prototype.PONG_INTERVAL = EverSocket.PONG_INTERVAL = 21000;// EverSocket.prototype.PING_INTERVAL = EverSocket.PING_INTERVAL = 10000;//心跳间隔 EverSocket.prototype.RECONN_INTERVAL = EverSocket.RECONN_INTERVAL = 5000;//重连的间隔 EverSocket.prototype.ERR_SOCKET_RECONNECT_FAILED =EverSocket.ERR_SOCKET_RECONNECT_FAILED=20001;//MCU自动重连失败,已经达到最大重连次数 EverSocket.prototype.CONNECTING = EverSocket.CONNECTING = 0; EverSocket.prototype.OPEN = EverSocket.OPEN = 1; EverSocket.prototype.CLOSING = EverSocket.CLOSING = 2; EverSocket.prototype.CLOSED = EverSocket.CLOSED = 3; EverSocket.prototype.MESSAGE = EverSocket.MESSAGE = 4; EverSocket.prototype.ERROR = EverSocket.ERROR = 5; export default new EverSocket();