gameClient/assets/scripts/wsclient.ts

141 lines
3.6 KiB
TypeScript
Raw Normal View History

2025-06-29 15:30:43 +08:00
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()
}
}