2025-07-05 16:16:50 +08:00
|
|
|
|
export class WsClient {
|
2025-06-29 15:30:43 +08:00
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
// 单例
|
2025-07-05 16:16:50 +08:00
|
|
|
|
public static Instance(): WsClient {
|
|
|
|
|
if (!this.instance) this.instance = new WsClient()
|
2025-06-29 15:30:43 +08:00
|
|
|
|
return this.instance
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-05 16:16:50 +08:00
|
|
|
|
// 是否连接
|
2025-06-29 15:30:43 +08:00
|
|
|
|
public get IsConnected(): boolean {
|
|
|
|
|
return this.isConnected
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 关闭WebSocket连接
|
2025-07-05 16:16:50 +08:00
|
|
|
|
Close() {
|
2025-06-29 15:30:43 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-05 16:16:50 +08:00
|
|
|
|
private async connectAsync(url?: string): Promise<WebSocket> {
|
2025-06-29 15:30:43 +08:00
|
|
|
|
if (this.socket && this.socket.readyState !== WebSocket.CLOSED) {
|
|
|
|
|
// 如果已有连接且未关闭
|
2025-07-05 16:16:50 +08:00
|
|
|
|
this.Close()
|
2025-06-29 15:30:43 +08:00
|
|
|
|
}
|
2025-07-05 16:16:50 +08:00
|
|
|
|
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
|
2025-06-29 15:30:43 +08:00
|
|
|
|
try {
|
2025-07-05 16:16:50 +08:00
|
|
|
|
console.log(`正在连接websocket服务器:${url}`)
|
|
|
|
|
this.socket = await this.connectAsync(url)
|
2025-06-29 15:30:43 +08:00
|
|
|
|
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)
|
2025-07-05 16:16:50 +08:00
|
|
|
|
await this.ScheduleReconnect()
|
2025-06-29 15:30:43 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 发送消息到服务器
|
2025-07-05 16:16:50 +08:00
|
|
|
|
Send(message: Uint8Array) {
|
2025-06-29 15:30:43 +08:00
|
|
|
|
if (!this.socket || this.socket.readyState !== WebSocket.OPEN) {
|
|
|
|
|
// 如果连接不存在或未打开
|
|
|
|
|
console.error('websocket未连接,无法发送消息')
|
|
|
|
|
return false
|
|
|
|
|
}
|
2025-07-05 16:16:50 +08:00
|
|
|
|
// var msg: string = ''
|
|
|
|
|
// if (typeof message == 'string') {
|
|
|
|
|
// msg = message
|
|
|
|
|
// } else {
|
|
|
|
|
// msg = JSON.stringify(message)
|
|
|
|
|
// }
|
|
|
|
|
this.socket.send(message)
|
2025-06-29 15:30:43 +08:00
|
|
|
|
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
|
2025-07-05 16:16:50 +08:00
|
|
|
|
// this.ScheduleReconnect()
|
2025-06-29 15:30:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 连接错误回调
|
|
|
|
|
private onError(error: Event) {
|
|
|
|
|
console.error('websocket发生错误:', error)
|
|
|
|
|
// 不需要在这里重连,onClose里会重连
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 重连
|
2025-07-05 16:16:50 +08:00
|
|
|
|
private async ScheduleReconnect() {
|
2025-06-29 15:30:43 +08:00
|
|
|
|
if (this.reconnectCount >= this.maxReconnectCount) {
|
|
|
|
|
console.error(`达到最大重连次数:${this.maxReconnectCount},停止重连`)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this.reconnectCount++
|
2025-07-05 16:16:50 +08:00
|
|
|
|
console.log(`尝试重连(${this.reconnectCount}/${this.maxReconnectCount})...`)
|
|
|
|
|
await this.connectAsync()
|
2025-06-29 15:30:43 +08:00
|
|
|
|
}
|
|
|
|
|
}
|