Files

431 lines
13 KiB
TypeScript

import { MessagePair, MessagePairRegistry } from '../../App/Msg/MessagePairBase';
import { DefaultNetConfig, NetConfig, NetProtocolType } from './NetConfig';
import { NetEvent } from './NetEvent';
import { ClientConfig, PlatformAdapter } from './PlatformAdapter';
import { INetClient } from './WebSocketClient';
/**
* 网络管理器单例
* 负责管理网络连接和消息通信
* 支持 HTTP 和 WebSocket 两种协议
*/
export class NetManager {
private static _instance: NetManager | null = null;
/** TSRPC Client 实例 (HttpClient 或 WsClient) */
private _client: INetClient | null = null;
/** 是否已连接 */
private _isConnected: boolean = false;
/** 网络配置 */
private _config: NetConfig | null = null;
/** 重连计数 */
private _reconnectCount: number = 0;
/** 重连定时器 */
private _reconnectTimer: any = null;
/** 事件监听器 */
private _eventListeners: Map<string, Function[]> = new Map();
private constructor() { }
/**
* 获取单例实例
*/
static getInstance(): NetManager {
if (!this._instance) {
this._instance = new NetManager();
}
return this._instance;
}
/**
* 设置服务协议 (必须在 init 之前调用)
* @param serviceProto 从 shared 目录导入的协议定义
*/
setServiceProto(serviceProto: any): void {
PlatformAdapter.setServiceProto(serviceProto);
}
/**
* 初始化网络管理器
* @param config 网络配置
*/
init(config: NetConfig): void {
this._config = {
...DefaultNetConfig,
...config
} as NetConfig;
console.log('[NetManager] Initialized with config:', this._config);
console.log('[NetManager] Protocol:', this._config.protocolType);
console.log('[NetManager] Platform:', PlatformAdapter.getPlatformInfo());
}
/**
* 连接服务器
*/
async connect(): Promise<boolean> {
try {
if (!this._config) {
console.error('[NetManager] Config not set, please call init() first');
return false;
}
console.log('[NetManager] Connecting to server:', this._config.serverUrl);
// 创建客户端配置
const clientConfig: ClientConfig = {
server: this._config.serverUrl,
protocolType: this._config.protocolType,
json: this._config.json,
timeout: this._config.timeout,
};
// 根据平台和协议类型创建对应的客户端
this._client = PlatformAdapter.createClient(clientConfig);
// 如果是 WebSocket 客户端,需要显式连接
if (this._config.protocolType === NetProtocolType.WebSocket && this._client.connect) {
this.emit(NetEvent.Connecting);
const result = await this._client.connect();
if (!result.isSucc) {
console.error('[NetManager] WebSocket connection failed:', result.errMsg);
this.emit(NetEvent.Error, result.errMsg);
// 尝试重连
if (this._config.autoReconnect) {
this.scheduleReconnect();
}
return false;
}
}
this._isConnected = true;
this._reconnectCount = 0;
this.emit(NetEvent.Connected);
console.log('[NetManager] Connected successfully');
return true;
} catch (error) {
console.error('[NetManager] Connection failed:', error);
this.emit(NetEvent.Error, error);
// 尝试重连
if (this._config?.autoReconnect) {
this.scheduleReconnect();
}
return false;
}
}
/**
* 断开连接
*/
disconnect(): void {
if (!this._isConnected || !this._client) {
return;
}
console.log('[NetManager] Disconnecting...');
// 清除重连定时器
if (this._reconnectTimer) {
clearTimeout(this._reconnectTimer);
this._reconnectTimer = null;
}
// 如果是 WebSocket 客户端,调用断开连接方法
if (this._client.disconnect) {
this._client.disconnect();
}
this._isConnected = false;
this._client = null;
this.emit(NetEvent.Disconnected);
console.log('[NetManager] Disconnected');
}
/**
* 调用 API
* @param apiName API 名称
* @param req 请求参数
*/
async callApi<Req, Res>(apiName: string, req: Req): Promise<Res | null> {
if (!this._isConnected || !this._client) {
console.error('[NetManager] Not connected');
return null;
}
try {
console.log(`[NetManager] Calling API: ${apiName}`, req);
const result = await this._client.callApi(apiName, req);
if (result.isSucc) {
console.log(`[NetManager] API ${apiName} success:`, result.res);
return result.res as Res;
} else {
console.error(`[NetManager] API ${apiName} failed:`, result.err);
return null;
}
} catch (error) {
console.error(`[NetManager] API ${apiName} error:`, error);
this.emit(NetEvent.Error, error);
return null;
}
}
/**
* 监听消息 (仅支持 WebSocket)
* @param msgName 消息名称
* @param handler 处理函数
*/
listenMsg(msgName: string, handler: Function): void {
if (!this._client) {
console.error('[NetManager] Client not initialized');
return;
}
if (!this._client.listenMsg) {
console.warn('[NetManager] Message listening not supported for HTTP client');
return;
}
console.log(`[NetManager] Listening message: ${msgName}`);
this._client.listenMsg(msgName, handler);
}
/**
* 取消监听消息 (仅支持 WebSocket)
* @param msgName 消息名称
* @param handler 处理函数(可选,不传则取消所有该消息的监听)
*/
unlistenMsg(msgName: string, handler?: Function): void {
if (!this._client) {
console.error('[NetManager] Client not initialized');
return;
}
if (!this._client.unlistenMsg) {
console.warn('[NetManager] Message listening not supported for HTTP client');
return;
}
console.log(`[NetManager] Unlisten message: ${msgName}`);
this._client.unlistenMsg(msgName, handler);
}
/**
* 发送消息并等待响应 (基于消息对系统)
* @param messagePair 消息对实例
* @param requestData 请求消息内容
* @returns Promise<响应消息>
*/
async callMsg<TReq, TRes>(messagePair: MessagePair<TReq, TRes>, requestData: TReq): Promise<TRes | null> {
if (!this._isConnected || !this._client) {
console.error('[NetManager] Not connected');
return null;
}
const requestName = messagePair.requestName;
const responseName = messagePair.responseName;
// 验证请求消息格式
if (!messagePair.isValidRequest(requestData)) {
console.error(`[NetManager] Invalid request data for ${requestName}:`, requestData);
return null;
}
console.log(`[NetManager] Calling message: ${requestName} -> ${responseName}`, requestData);
return new Promise<TRes | null>((resolve, reject) => {
// 创建一次性响应处理器
const responseHandler = (response: TRes) => {
// 验证响应消息格式
if (!messagePair.isValidResponse(response)) {
return;
}
// 取消监听
this.unlistenMsg(responseName, responseHandler);
// 返回响应
console.log(`[NetManager] Received response for ${requestName}:`, response);
resolve(response);
};
// 监听响应
this.listenMsg(responseName, responseHandler);
// 发送请求消息
this.sendMsg(requestName, requestData);
// 设置超时处理
const timeout = this._config?.timeout || 30000;
setTimeout(() => {
this.unlistenMsg(responseName, responseHandler);
console.error(`[NetManager] Request timeout for ${requestName}`);
resolve(null);
}, timeout);
});
}
/**
* 发送消息 (仅支持 WebSocket)
* @param msgName 消息名称
* @param msg 消息内容
*/
sendMsg(msgName: string, msg: any): void {
if (!this._isConnected || !this._client) {
console.error('[NetManager] Not connected');
return;
}
if (!this._client.sendMsg) {
console.warn('[NetManager] Message sending not supported for HTTP client');
return;
}
console.log(`[NetManager] Sending message: ${msgName}`, msg);
this._client.sendMsg(msgName, msg);
}
/**
* 安排重连
*/
private scheduleReconnect(): void {
if (!this._config) {
return;
}
if (this._reconnectCount >= (this._config.maxReconnectTimes || 5)) {
console.error('[NetManager] Max reconnect times reached');
this.emit(NetEvent.ReconnectFailed);
return;
}
this._reconnectCount++;
console.log(`[NetManager] Scheduling reconnect (${this._reconnectCount}/${this._config.maxReconnectTimes})...`);
this.emit(NetEvent.Reconnecting, this._reconnectCount);
this._reconnectTimer = setTimeout(() => {
this.reconnect();
}, this._config.reconnectInterval || 3000);
}
/**
* 重新连接
*/
private async reconnect(): Promise<void> {
console.log('[NetManager] Reconnecting...');
const success = await this.connect();
if (success) {
this.emit(NetEvent.ReconnectSuccess);
} else if (this._config?.autoReconnect) {
this.scheduleReconnect();
}
}
/**
* 监听网络事件
* @param event 事件名称
* @param callback 回调函数
*/
on(event: NetEvent, callback: Function): void {
if (!this._eventListeners.has(event)) {
this._eventListeners.set(event, []);
}
this._eventListeners.get(event)!.push(callback);
}
/**
* 取消监听网络事件
* @param event 事件名称
* @param callback 回调函数
*/
off(event: NetEvent, callback: Function): void {
const listeners = this._eventListeners.get(event);
if (listeners) {
const index = listeners.indexOf(callback);
if (index > -1) {
listeners.splice(index, 1);
}
}
}
/**
* 触发事件
* @param event 事件名称
* @param args 事件参数
*/
private emit(event: NetEvent, ...args: any[]): void {
const listeners = this._eventListeners.get(event);
if (listeners) {
listeners.forEach(callback => {
try {
callback(...args);
} catch (error) {
console.error('[NetManager] Event callback error:', error);
}
});
}
}
/**
* 获取连接状态
*/
get isConnected(): boolean {
return this._isConnected;
}
/**
* 获取客户端实例
*/
get client(): INetClient | null {
return this._client;
}
/**
* 获取协议类型
*/
get protocolType(): NetProtocolType | undefined {
return this._config?.protocolType;
}
/**
* 判断是否为 WebSocket 连接
*/
get isWebSocket(): boolean {
return this._config?.protocolType === NetProtocolType.WebSocket;
}
/**
* 判断是否为 HTTP 连接
*/
get isHttp(): boolean {
return this._config?.protocolType === NetProtocolType.Http;
}
/**
* 获取所有已注册的消息对信息
* @returns 消息对列表
*/
getMessagePairs(): { requestName: string; responseName: string }[] {
const registry = MessagePairRegistry.getInstance();
return registry.getAllPairs().map(pair => ({
requestName: pair.requestName,
responseName: pair.responseName
}));
}
}