wo-base-websocket-server/basesocket.js
2024-02-06 09:11:51 +08:00

108 lines
4.1 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const ws = require('ws')
const webtoken = require('wo-base-webtoken')
const my = {
wsServer: undefined,
socketPool: {},
listeners: {},
}
module.exports = {
initSocket (webServer) {
my.wsServer = new ws.Server({ server: webServer })
console.info({ _at: new Date().toJSON(), _from: 'Socket:initSocket', _type: 'CLOG', about: 'Base Socket Server is initialized.' }, '\n,')
my.wsServer.on('connection', (socket, req) => {
//console.info({_at:new Date().toJSON(), _from: 'Socket:onConnection', _type:'CLOG', about: `A socket is connecting from ${req.connection.remoteAddress}:${req.connection.remotePort}.`},'\n,')
// socket.isAlive = true
// socket.on('pong', function() { this.isAlive = true })
socket.on('message', (data) => {
// 在这里统一分发消息
let dataObj
try {
dataObj = JSON.parse(data)
if (dataObj?.skevent === 'PING') {
return
}
console.log({ _at: new Date().toJSON(), _from: 'Socket:onMessage', _type: 'CLOG', usid: socket.usid, dataObj }, '\n,')
} catch (exception) {
console.error({ _at: new Date().toJSON(), _from: 'Socket:onMessage', _type: 'CERROR', about: 'Unable to parse socket message', data }, '\n,')
return
}
if (['SOCKET_OWNER', 'SOCKET_OWNER_RECONNECT'].includes(dataObj.skevent)) {
// 前端断线重连时,并不会自动再次提供 _passtoken。在前端的initSocket时应当把_passtoken送过来而后台则对_passtoken做验证后再加socketPool。
dataObj._passtokenSource = webtoken.verifyToken(dataObj._passtoken)
if (typeof dataObj._passtokenSource?.usid === 'string') {
my.socketPool[dataObj._passtokenSource.usid] = socket
socket.usid = dataObj._passtokenSource.usid
console.log({
_at: new Date().toJSON(), _from: 'Socket:onMessage', _type: 'CLOG',
skevent: dataObj.skevent,
usid: dataObj._passtokenSource.usid,
socketPool: Object.keys(my.socketPool)?.length,
socketClients: my.wsServer.clients.size
}, '\n,')
}
}
const listeners = my.listeners[dataObj.skevent] || []
for (const listener of listeners) {
listener(dataObj)
}
})
// const heartbeat = setInterval(() => {
// my.wsServer.clients.forEach((socket) => {
// if (socket.isAlive === false) return socket.terminate()
// socket.isAlive = false
// socket.ping(function() { wo.cclog('👉 ASS: sent Ping') })
// })
// }, 60000)
socket.on('close', () => {
//console.log({_at:new Date().toJSON(), _from: 'Socket:onClose', _type:'CLOG', usid: socket?.usid},'\n,') // don't know why, but this output happens too often without usid.
delete my.socketPool[socket?.usid]
// clearInterval(heartbeat)
})
})
return this
},
removeUserSocket (usid) {
delete my.socketPool[usid]
},
addListener (skevent, listener) {
if (Array.isArray(my.listeners[skevent]) && typeof listener === 'function') {
my.listeners[skevent].push(listener)
} else {
my.listeners[skevent] = [listener]
}
return this
},
sendToAll (dataObj) {
my.wsServer.clients.forEach((socket) => {
if (socket.readyState === socket.OPEN) {
socket.send(typeof dataObj !== 'string' ? JSON.stringify(dataObj) : dataObj)
} else {
console.error({ _at: new Date().toJSON(), _from: 'Socket:sendToAll', _type: 'CWARN', msg: 'sendToAll: Failed sending to unconnected socket', dataObj, usid: socket.usid }, '\n,')
delete my.socketPool[socket.usid]
}
})
},
sendToOne (dataObj, usid) {
const socket = my.socketPool[usid]
if (socket && socket.readyState === socket.OPEN) {
socket.send(typeof dataObj !== 'string' ? JSON.stringify(dataObj) : dataObj)
} else {
console.error({ _at: new Date().toJSON(), _from: 'Socket:sendToOne', _type: 'CWARN', msg: 'sendToOne: Failed sending to unconnected socket', dataObj, usid }, '\n,')
delete my.socketPool[usid]
}
},
}