import { _decorator, Component, Node } from 'cc' const { ccclass, property } = _decorator @ccclass('WsClient') export class WsClient extends Component { private socket: WebSocket | null = null private url: string = 'ws://echo.websocket.org' // 测试服务器 private reconnectTimerId: number = 0 private maxReconnectCount: number = 5 private reconnectCount: number = 0 private isConnected: boolean = false private static instance: WsClient = null // 单例 public static get Instance(): WsClient { return this.instance } public get IsConnected(): boolean { return this.isConnected } // 组件加载时自动调用 protected onLoad(): void { if (WsClient.instance) { this.destroy() return } WsClient.instance = this this.node.name = 'WsClient' this.node.addComponent(WsClient) } // 关闭WebSocket连接 close() { if (this.reconnectTimerId > 0) { clearTimeout(this.reconnectTimerId) this.reconnectTimerId = 0 } if (this.socket) { // 清空所有事件处理函数 this.socket.onopen = null this.socket.onmessage = null this.socket.onclose = null this.socket.onerror = null this.socket.close() this.socket = null } this.isConnected = false } // 连接websocket服务器 connect(url?: string) { if (url) this.url = url if (this.socket && this.socket.readyState !== WebSocket.CLOSED) { // 如果已有连接且未关闭 this.close() } try { this.socket = new WebSocket(this.url) this.socket.onopen = this.onOpen.bind(this) this.socket.onmessage = this.onMessage.bind(this) this.socket.onclose = this.onClose.bind(this) this.socket.onerror = this.onError.bind(this) this.reconnectCount = 0 this.isConnected = true console.log(`正在连接websocket服务器:${this.url}`) } catch (error) { console.error('创建websocket失败:', error) this.scheduleReconnect() } } // 发送消息到服务器 send(message: string | object) { if (!this.socket || this.socket.readyState !== WebSocket.OPEN) { // 如果连接不存在或未打开 console.error('websocket未连接,无法发送消息') return false } var msg: string = '' if (typeof message == 'string') { msg = message } else { msg = JSON.stringify(message) } this.socket.send(msg) return true } // 连接成功回调 private onOpen() { console.log('websocket连接已建立') this.reconnectCount = 0 } // 收到消息回调 private onMessage(event: MessageEvent) { console.log('收到消息:', event.data) window.dispatchEvent(new CustomEvent('ws-message', { detail: event.data })) } // 连接关闭回调 private onClose(event: CloseEvent) { console.log('websocket连接已关闭,代码:', event.code, '原因:', event.reason) this.socket = null this.scheduleReconnect() } // 连接错误回调 private onError(error: Event) { console.error('websocket发生错误:', error) // 不需要在这里重连,onClose里会重连 } // 重连 private scheduleReconnect() { if (this.reconnectCount >= this.maxReconnectCount) { console.error(`达到最大重连次数:${this.maxReconnectCount},停止重连`) return } this.reconnectCount++ const delay = 2000 console.log( `尝试重连(${this.reconnectCount}/${this.maxReconnectCount}),${ delay / 1000 }秒后...` ) this.reconnectTimerId = setTimeout(() => { this.connect() }, delay) } // 组件销毁时自动调用 protected onDestroy(): void { this.close() } }