/** * WebSocket通信服务模块 * 负责与后端WebSocket通信、连接管理和消息处理 */ import { ref } from 'vue'; class WebSocketService { constructor() { this.socket = null; this.wsUrl = ref('ws://127.0.0.1:5005/ws'); this.reconnectInterval = 1000; // 重连间隔(毫秒) this.reconnectTimer = null; this.pingInterval = null; this.messageHandlers = new Map(); // 消息处理器映射 this.isConnecting = false; } /** * 设置WebSocket服务器URL * @param {string} url - WebSocket服务器URL(ws://或wss://协议) */ setWsUrl(url) { this.wsUrl.value = url; console.log('WebSocket URL已设置为:', url); } /** * 注册消息处理器 * @param {string} messageType - 消息类型 * @param {Function} handler - 处理函数,接收消息数据参数 */ registerHandler(messageType, handler) { this.messageHandlers.set(messageType, handler); } /** * 移除消息处理器 * @param {string} messageType - 要移除处理器的消息类型 */ removeHandler(messageType) { this.messageHandlers.delete(messageType); } /** * 清除所有消息处理器 */ clearHandlers() { this.messageHandlers.clear(); } /** * 连接到WebSocket服务器 */ connect() { if (this.isConnecting || (this.socket && this.socket.readyState === WebSocket.OPEN)) { console.log('WebSocket已连接或正在连接中,不需要重新连接'); return; } this.isConnecting = true; try { console.log('尝试连接WebSocket:', this.wsUrl.value); this.socket = new WebSocket(this.wsUrl.value); this.socket.onopen = () => { console.log('WebSocket连接成功'); this.isConnecting = false; // 发送初始化请求,请求当前状态 this.sendMessage({ type: 'request_status' }); if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; } // 启动定期ping,保持连接活跃 this.startPingInterval(); }; this.socket.onmessage = (event) => { this.handleMessage(event); }; this.socket.onclose = (event) => { console.log(`WebSocket连接关闭,代码: ${event.code},原因: ${event.reason}`); this.isConnecting = false; this.socket = null; // 清理ping定时器 if (this.pingInterval) { clearInterval(this.pingInterval); this.pingInterval = null; } // 尝试重连 this.scheduleReconnect(); }; this.socket.onerror = (error) => { console.error('WebSocket错误:', error); this.isConnecting = false; }; } catch (error) { console.error('创建WebSocket连接错误:', error); this.isConnecting = false; // 连接失败时也应设置重连 this.scheduleReconnect(); } } /** * 安排重新连接 */ scheduleReconnect() { if (!this.reconnectTimer) { this.reconnectTimer = setTimeout(() => { console.log('尝试重新连接WebSocket...'); this.reconnectTimer = null; this.connect(); }, this.reconnectInterval); } } /** * 启动定期发送ping消息的定时器 */ startPingInterval() { // 清理现有的ping定时器 if (this.pingInterval) { clearInterval(this.pingInterval); } // 每10秒发送一次ping消息保持连接 this.pingInterval = setInterval(() => { this.sendPing(); }, 10000); } /** * 发送ping消息 */ sendPing() { if (this.socket?.readyState === WebSocket.OPEN) { console.log('发送ping消息保持连接'); this.sendMessage({ type: 'ping' }); } } /** * 发送消息到WebSocket服务器 * @param {Object} data - 要发送的消息对象 * @returns {boolean} - 是否成功发送 */ sendMessage(data) { if (!this.socket || this.socket.readyState !== WebSocket.OPEN) { console.warn('WebSocket未连接,无法发送消息'); return false; } try { this.socket.send(JSON.stringify(data)); return true; } catch (error) { console.error('发送WebSocket消息失败:', error); return false; } } /** * 处理接收到的WebSocket消息 * @param {MessageEvent} event - WebSocket消息事件 */ handleMessage(event) { try { const data = JSON.parse(event.data); console.log('收到WebSocket消息类型:', data.type); // 心跳:服务器发来的 ping,需要立即回复 pong 保持连接 if (data && data.type === 'ping') { this.sendMessage({ type: 'pong' }); return; } // 调用对应类型的消息处理器 if (data.type && this.messageHandlers.has(data.type)) { this.messageHandlers.get(data.type)(data); } else { console.log('没有对应的处理器,消息类型:', data.type); } } catch (error) { console.error('处理WebSocket消息错误:', error, '原始数据:', event.data); } } /** * 检查并恢复WebSocket连接 */ checkAndRestoreConnection() { console.log('检查WebSocket连接状态'); if (!this.socket || this.socket.readyState === WebSocket.CLOSED || this.socket.readyState === WebSocket.CLOSING) { console.log('WebSocket未连接或已关闭,尝试重新连接'); this.connect(); } } /** * 关闭WebSocket连接 */ disconnect() { // 清理ping定时器 if (this.pingInterval) { clearInterval(this.pingInterval); this.pingInterval = null; } // 清理重连定时器 if (this.reconnectTimer) { clearTimeout(this.reconnectTimer); this.reconnectTimer = null; } // 关闭WebSocket连接 if (this.socket) { try { this.socket.close(); } catch (error) { console.error('关闭WebSocket连接错误:', error); } this.socket = null; } } } // 创建单例实例 const websocketService = new WebSocketService(); export default websocketService;