http://www.ruanyifeng.com/blog/2017/05/websocket.html
https://github.com/theturtle32/WebSocket-Node
npm install websocket // "websocket": "^1.0.32",
import WebSocketClient from 'websocket'
/*心跳检测*/
class heartCheck {
constructor(e) {
this.timeout = 60000 //60秒
this.timeoutObj = null
this.serverTimeoutObj = null
}
reset() {
clearTimeout(this.timeoutObj)
clearTimeout(this.serverTimeoutObj)
return this
}
start(websock) {
this.timeoutObj = setTimeout(function () {
//这里发送一个心跳,后端收到后,返回一个心跳消息,
//onmessage拿到返回的心跳就说明连接正常
websock.send("HeartBeat")
this.serverTimeoutObj = setTimeout(function () {//如果超过一定时间还没重置,说明后端主动断开了
websock.close()//如果onclose会执行reconnect,我们执行ws.close()就行了.如果直接执行reconnect 会触发onclose导致重连两次
}, this.timeout)
}, this.timeout)
}
}
export default class websocket {
constructor(wsurl, callback) {
if(callback && typeof callback === 'function'){
this.global_callback = callback
}else{
this.global_callback = null
}
this.lockReconnect = false;//避免重复连接
this.initWebSocket(wsurl, callback)
}
initWebSocket(wsurl, callback) {
this.websock = new WebSocketClient.w3cwebsocket(wsurl, 'echo-protocol')
/*初始化weosocket*/
this.websock.onopen = () => {
// 连接成功
console.log('连接成功')
};
this.websock.onerror = () => {
// 初始化失败,继续连接
if (this.lockReconnect) return;
this.lockReconnect = true;
setTimeout(() => {
new websocket(wsurl, callback)
this.lockReconnect = false;
}, 2000);
};
this.websock.onmessage = (e) => {
// 接收数据
new heartCheck().reset().start(this.websock)
this.websocketOnMessage(e);
};
this.websock.onclose = (e) => {
// 关闭
this.websock.close();
this.global_callback = null;
};
}
/*实际调用的方法
* 1.若是ws开启状态
* 2.若是 正在开启状态,则等待1s后重新调用
* 3.若未开启 ,则等待1s后重新调用
* */
sendSock(agentData, callback) {
if (callback) {
if (typeof callback === 'function') {
this.global_callback = callback
} else {
this.global_callback = data => {
}
alert('sendSock,传参没有回调')
}
}
if (this.websock.readyState === this.websock.OPEN) {
this.websock.send(agentData)
} else {
setTimeout(() => {
this.sendSock(agentData)
}, 1000)
}
}
// 关闭
websocketclose(e) {
// console.log("WebSocket关闭成功");
this.websock.close()
this.global_callback = null
}
// 接收数据
websocketOnMessage(e) {
try {
this.global_callback(e.data)
} catch (err) {
}
}
}
import websocket from '../assets/js/websocket'
created() {
// 初始化 这里的回调:在不发送数据时,其他链接发送了数据,通过这个回调接收数据
this.socketServe = new websocket('ws://localhost:3001', data => {})
//页面销毁时关闭长连接
window.addEventListener("beforeunload ", () => {
this.socketServe.websocketclose();
});
},
beforeDestroy() {
//页面销毁时关闭长连接
this.socketServe.websocketclose();
},
// 这里的回调,会覆盖掉 init 时的回调
this.socketServe.sendSock(JSON.stringify({
id: this.$store.state.userInfo.id,
type: this.type
}), data => {
console.log(data)
})
websocket.js
文档
export default class SocketService {
// 单例
static instance = null
static get Instance() {
if (!this.instance) {
this.instance = new SocketService()
}
return this.instance
}
// 和服务端连接的socket对象
ws = null
// 存储回调函数
callBackMapping = {}
// 标识是否连接成功
connected = false
// 记录重试的次数
sendRetryCount = 0
// 重新连接尝试的次数
connectRetryCount = 0
// 定义连接服务器的方法
connect() {
// 连接服务器
if (!window.WebSocket) {
return console.log('您的浏览器不支持WebSocket')
}
this.ws = new WebSocket('ws://localhost:3001', 'echo-protocol')
// 连接成功的事件
this.ws.onopen = () => {
console.log('连接服务端成功了')
this.connected = true
// 重置重新连接的次数
this.connectRetryCount = 0
}
// 1.连接服务端失败
// 2.当连接成功之后, 服务器关闭的情况
this.ws.onclose = () => {
console.log('连接服务端失败')
this.connected = false
this.connectRetryCount++
setTimeout(() => {
this.connect()
}, 500 * this.connectRetryCount)
}
// 得到服务端发送过来的数据
this.ws.onmessage = msg => {
console.log(msg.data, '从服务端获取到了数据')
}
}
// 回调函数的注册
registerCallBack (socketType, callBack) {
this.callBackMapping[socketType] = callBack
}
// 取消某一个回调函数
unRegisterCallBack (socketType) {
this.callBackMapping[socketType] = null
}
// 发送数据的方法
send (data) {
// 判断此时此刻有没有连接成功
if (this.connected) {
this.sendRetryCount = 0
try {
this.ws.send(JSON.stringify(data))
}catch (e) {
this.ws.send(data)
}
} else {
this.sendRetryCount++
setTimeout(() => {
this.send(data)
}, this.sendRetryCount * 500)
}
}
}
vue
组件中 init
import SocketService from '../assets/js/websocket'
data() {
return {
socketServe: null
}
},
methods: {
sendData() {
this.socketServe.send('这里是HTML发送的数据', data => {
console.log(data)
})
},
},
created() {
SocketService.Instance.connect()
this.socketServe= SocketService.Instance
// 注册接收到数据的回调函数
this.socketServe.registerCallBack('callback1', data => {
console.log(data)
})
},
beforeDestroy() {
// 销毁某一个回调函数
this.socketServe.registerCallBack('callback1')
},
node
代码ws
npm install ws // "ws": "^7.3.0",
web_socket_service.js
文件const WebSocket = require('ws')
// 创建WebSocket服务端的对象, 绑定的端口号是3001
const wss = new WebSocket.Server({
port: 3001
})
// 服务端开启了监听
module.exports.listen = () => {
// 对客户端的连接事件进行监听
// client:代表的是客户端的连接socket对象
wss.on('connection', client => {
console.log('有客户端连接成功了...')
// 对客户端的连接对象进行message事件的监听
// msg: 由客户端发给服务端的数据
client.on('message',async msg => {
console.log('客户端发送数据给服务端了: ' + msg)
// client.send('hello socket from backend')
wss.clients.forEach(client => {
client.send(msg)
})
})
})
}
app.js
中添加const webSocketService = require('./websocket/web_socket_service')
// 开启服务端的监听, 监听客户端的连接
// 当某一个客户端连接成功之后, 就会对这个客户端进行message事件的监听
webSocketService.listen()