const WebSocket = require('ws') const { v4: uuidv4 } = require('uuid') class ChatServer { constructor(server) { this.wss = new WebSocket.Server({ server }) this.clients = new Map() // 存储所有连接的客户端 this.messageHistory = [] // 存储消息历史 this.setupWebSocket() this.setupHeartbeat() } setupWebSocket() { this.wss.on('connection', (ws, req) => { const clientId = uuidv4() const userInfo = { id: clientId, name: '未命名用户' } // 存储客户端连接 this.clients.set(clientId, { ws, userInfo, lastPing: Date.now() }) // 广播新用户加入 this.broadcast({ type: 'system', action: 'join', user: userInfo, users: Array.from(this.clients.values()).map(client => client.userInfo), timestamp: Date.now() }) // 发送在线用户列表 ws.send(JSON.stringify({ type: 'system', action: 'userList', users: Array.from(this.clients.values()).map(client => client.userInfo), timestamp: Date.now() })) // 发送历史消息 ws.send(JSON.stringify({ type: 'system', action: 'history', messages: this.messageHistory.slice(-50), // 最近50条消息 timestamp: Date.now() })) // 处理消息 ws.on('message', (data) => { try { const message = JSON.parse(data) const client = this.clients.get(clientId) if (client) { client.lastPing = Date.now() // 更新最后活动时间 } switch (message.type) { case 'chat': // 处理聊天消息 const chatMessage = { id: uuidv4(), type: 'chat', from: userInfo, to: message.to, // null表示群发 content: message.content, timestamp: Date.now() } this.messageHistory.push(chatMessage) if (message.to) { // 私聊消息 const targetClient = this.clients.get(message.to.id) if (targetClient) { targetClient.ws.send(JSON.stringify(chatMessage)) ws.send(JSON.stringify(chatMessage)) // 发送给自己 } } else { // 群发消息 this.broadcast(chatMessage) } break case 'user': // 更新用户信息 if (message.action === 'update') { userInfo.name = message.name this.broadcast({ type: 'system', action: 'userUpdate', user: userInfo, users: Array.from(this.clients.values()).map(client => client.userInfo), timestamp: Date.now() }) } break case 'ping': // 处理心跳消息 ws.send(JSON.stringify({ type: 'pong', timestamp: Date.now() })) break } } catch (error) { console.error('处理消息时出错:', error) } }) // 处理连接关闭 ws.on('close', () => { this.clients.delete(clientId) this.broadcast({ type: 'system', action: 'leave', user: userInfo, users: Array.from(this.clients.values()).map(client => client.userInfo), timestamp: Date.now() }) }) // 处理错误 ws.on('error', (error) => { console.error('WebSocket错误:', error) this.clients.delete(clientId) }) }) } // 设置心跳检测 setupHeartbeat() { const HEARTBEAT_INTERVAL = 30000 // 30秒检查一次 const CLIENT_TIMEOUT = 60000 // 60秒超时 setInterval(() => { const now = Date.now() this.clients.forEach((client, clientId) => { if (now - client.lastPing > CLIENT_TIMEOUT) { console.log(`客户端 ${clientId} 超时断开`) client.ws.terminate() this.clients.delete(clientId) } }) }, HEARTBEAT_INTERVAL) } // 广播消息给所有客户端 broadcast(message) { const messageStr = JSON.stringify(message) this.clients.forEach(client => { if (client.ws.readyState === WebSocket.OPEN) { client.ws.send(messageStr) } }) } // 清理历史消息 cleanHistory() { const oneDay = 24 * 60 * 60 * 1000 // 一天的毫秒数 const now = Date.now() this.messageHistory = this.messageHistory.filter(msg => { return (now - msg.timestamp) < oneDay }) } } module.exports = ChatServer