初识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');
});