const { Server: ServerIO } = require('socket.io') const { io: ClientIO } = require('socket.io-client') const { clientPort } = require('../config') const { verifyAuth } = require('../utils') let hostSockets = {} function getHostInfo(serverSocket, host) { let hostSocket = ClientIO(`http://${ host }:${ clientPort }`, { path: '/client/os-info', forceNew: false, timeout: 5000, reconnectionDelay: 3000, reconnectionAttempts: 100 }) // 将与客户端连接的socket实例保存起来,web端断开时关闭与客户端的连接 hostSockets[serverSocket.id] = hostSocket hostSocket .on('connect', () => { consola.success('host-status-socket连接成功:', host) hostSocket.on('client_data', (data) => { serverSocket.emit('host_data', data) }) hostSocket.on('client_error', () => { serverSocket.emit('host_data', null) }) }) .on('connect_error', (error) => { consola.error('host-status-socket连接[失败]:', host, error.message) serverSocket.emit('host_data', null) }) .on('disconnect', () => { consola.info('host-status-socket连接[断开]:', host) serverSocket.emit('host_data', null) }) } module.exports = (httpServer) => { const serverIo = new ServerIO(httpServer, { path: '/host-status', cors: { origin: '*' // 需配置跨域 } }) serverIo.on('connection', (serverSocket) => { // 前者兼容nginx反代, 后者兼容nodejs自身服务 let clientIp = serverSocket.handshake.headers['x-forwarded-for'] || serverSocket.handshake.address serverSocket.on('init_host_data', ({ token, host }) => { // 校验登录态 const { code, msg } = verifyAuth(token, clientIp) if(code !== 1) { serverSocket.emit('token_verify_fail', msg || '鉴权失败') serverSocket.disconnect() return } // 获取客户端数据 getHostInfo(serverSocket, host) consola.info('host-status-socket连接socketId: ', serverSocket.id, 'host-status-socket已连接数: ', Object.keys(hostSockets).length) // 关闭连接 serverSocket.on('disconnect', () => { // 当web端与服务端断开连接时, 服务端与每个客户端的socket也应该断开连接 let socket = hostSockets[serverSocket.id] socket.close && socket.close() delete hostSockets[serverSocket.id] consola.info('host-status-socket剩余连接数: ', Object.keys(hostSockets).length) }) }) }) }