import { ClientMsg } from '../network/pbExport' import { MessageDispatcher } from '../network/messageDispatcher' import { MessageDecoder } from '../network/messageDecoder' export class WsClient { 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 private static netEvent: EventTarget = null // 单例 public static get Instance(): WsClient { if (!this.instance) this.instance = new WsClient() return this.instance } // 网络事件中心 public static EventMgr(): EventTarget { if (!this.netEvent) this.netEvent = new EventTarget() return this.netEvent } // 是否连接 public get IsConnected(): boolean { return this.isConnected } // 关闭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 } private async connectAsync(url?: string): Promise { if (this.socket && this.socket.readyState !== WebSocket.CLOSED) { // 如果已有连接且未关闭 this.Close() } return new Promise((resolve, reject) => { const ws = new WebSocket(url) ws.onopen = () => resolve(ws) ws.onerror = (err) => reject(err) ws.onclose = () => reject(new Error('连接已关闭')) }) } // // 使用示例 // async function sendMessage() { // try { // const ws = await connectWebSocket(); // console.log('连接已建立'); // ws.send('同步发送消息'); // } catch (err) { // console.error('连接失败:', err); // } // } // 连接websocket服务器 async ConnectAsync(url?: string) { if (url) this.url = url url = this.url try { console.log(`正在连接websocket服务器:${url}`) this.socket = await this.connectAsync(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 } catch (error) { console.error('创建websocket失败:', error) await this.ScheduleReconnect() } } // 发送消息到服务器 Send(sid: number, msgId: number, msg: Uint8Array) { if (!this.socket || this.socket.readyState !== WebSocket.OPEN) { // 如果连接不存在或未打开 console.error('websocket未连接,无法发送消息') return false } const clinetMsg = new ClientMsg() clinetMsg.msgId = msgId clinetMsg.data = msg clinetMsg.serviceTid = sid const buffer = ClientMsg.encode(clinetMsg).finish() this.socket.send(buffer) return true } // 连接成功回调 private onOpen() { console.log('websocket连接已建立') this.reconnectCount = 0 } // 收到消息回调 private async onMessage(event: MessageEvent) { try { const buffer = await event.data.arrayBuffer() const uint8Array = new Uint8Array(buffer) // console.log('收到消息:', uint8Array) const cMsg = ClientMsg.decode(uint8Array) // console.log('收到消息:', MessageDecoder.Uint8ToHex(uint8Array)) const [msg, err] = MessageDecoder.Decode(cMsg.msgId, cMsg.data) if (err) { console.error(err) return } MessageDispatcher.Instance.Dispatch(cMsg.msgId, msg) } catch (error) { console.error('解析网络消息失败:', error) } } // 连接关闭回调 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 async ScheduleReconnect() { if (this.reconnectCount >= this.maxReconnectCount) { console.error(`达到最大重连次数:${this.maxReconnectCount},停止重连`) return } this.reconnectCount++ console.log(`尝试重连(${this.reconnectCount}/${this.maxReconnectCount})...`) await this.connectAsync() } }