gameClient/assets/scripts/wsclient.ts
2025-06-29 15:30:43 +08:00

141 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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()
}
}