""" 消息路由系统模块 负责处理客户端和服务器之间的消息传递 """ import time import threading import json import uuid from typing import Dict, Any, List, Optional, Callable class MessageRouter: """ 消息路由器 负责处理客户端和服务器之间的消息传递 """ def __init__(self, plugin): """ 初始化消息路由器 Args: plugin: 服务器架构插件实例 """ self.plugin = plugin self.enabled = False self.initialized = False # 消息配置 self.message_config = { "enable_compression": True, "enable_encryption": False, "max_message_size": 65536, "enable_message_queue": True, "max_queue_size": 10000, "enable_broadcast": True, "enable_message_filtering": True, "enable_message_logging": True, "log_level": "INFO" } # 消息处理器映射 self.message_handlers = {} # 消息队列 self.message_queue = [] self.message_queue_lock = threading.RLock() # 消息统计 self.message_stats = { "messages_received": 0, "messages_sent": 0, "messages_routed": 0, "messages_dropped": 0, "broadcast_messages": 0, "handler_errors": 0, "bytes_received": 0, "bytes_sent": 0, "errors": 0 } # 回调函数 self.message_callbacks = { "message_received": [], "message_sent": [], "message_routed": [], "message_error": [], "broadcast_sent": [] } # 时间戳记录 self.last_message_time = 0.0 self.last_queue_process = 0.0 print("✓ 消息路由器已创建") def initialize(self) -> bool: """ 初始化消息路由器 Returns: 是否初始化成功 """ try: print("正在初始化消息路由器...") # 注册默认消息处理器 self._register_default_handlers() self.initialized = True print("✓ 消息路由器初始化完成") return True except Exception as e: print(f"✗ 消息路由器初始化失败: {e}") self.message_stats["errors"] += 1 import traceback traceback.print_exc() return False def _register_default_handlers(self): """注册默认消息处理器""" try: self.register_message_handler("ping", self._handle_ping) self.register_message_handler("pong", self._handle_pong) self.register_message_handler("heartbeat", self._handle_heartbeat) self.register_message_handler("auth", self._handle_auth) self.register_message_handler("chat", self._handle_chat) self.register_message_handler("join_room", self._handle_join_room) self.register_message_handler("leave_room", self._handle_leave_room) self.register_message_handler("sync_data", self._handle_sync_data) print("✓ 默认消息处理器已注册") except Exception as e: print(f"✗ 默认消息处理器注册失败: {e}") def enable(self) -> bool: """ 启用消息路由器 Returns: 是否启用成功 """ try: if not self.initialized: print("✗ 消息路由器未初始化") return False self.enabled = True print("✓ 消息路由器已启用") return True except Exception as e: print(f"✗ 消息路由器启用失败: {e}") self.message_stats["errors"] += 1 import traceback traceback.print_exc() return False def disable(self): """禁用消息路由器""" try: self.enabled = False # 清空消息队列 with self.message_queue_lock: self.message_queue.clear() print("✓ 消息路由器已禁用") except Exception as e: print(f"✗ 消息路由器禁用失败: {e}") self.message_stats["errors"] += 1 import traceback traceback.print_exc() def finalize(self): """清理消息路由器资源""" try: # 禁用路由器 if self.enabled: self.disable() # 清理回调和处理器 self.message_callbacks.clear() self.message_handlers.clear() self.initialized = False print("✓ 消息路由器资源已清理") except Exception as e: print(f"✗ 消息路由器资源清理失败: {e}") import traceback traceback.print_exc() def update(self, dt: float): """ 更新消息路由器状态 Args: dt: 时间增量(秒) """ try: if not self.enabled: return current_time = time.time() self.last_message_time = current_time # 处理消息队列 if self.message_config["enable_message_queue"]: self._process_message_queue() except Exception as e: print(f"✗ 消息路由器更新失败: {e}") self.message_stats["errors"] += 1 import traceback traceback.print_exc() def _process_message_queue(self): """处理消息队列""" try: current_time = time.time() if current_time - self.last_queue_process < 0.01: # 限制处理频率 return processed_messages = 0 max_messages_per_update = 100 # 每次更新最多处理100条消息 with self.message_queue_lock: while self.message_queue and processed_messages < max_messages_per_update: try: message_data = self.message_queue.pop(0) self._route_message_internal( message_data["message"], message_data["client_address"], message_data["client_socket"], message_data["client_id"] ) processed_messages += 1 except Exception as e: print(f"✗ 队列消息处理失败: {e}") self.message_stats["errors"] += 1 processed_messages += 1 # 避免无限循环 self.last_queue_process = current_time except Exception as e: print(f"✗ 消息队列处理失败: {e}") self.message_stats["errors"] += 1 def route_message(self, message: bytes, client_address: tuple, client_socket, client_id: str = None): """ 路由消息 Args: message: 消息数据 client_address: 客户端地址 client_socket: 客户端套接字 client_id: 客户端ID(可选) """ try: if not self.enabled: return self.message_stats["messages_received"] += 1 self.message_stats["bytes_received"] += len(message) # 触发消息接收回调 self._trigger_message_callback("message_received", { "message_size": len(message), "client_address": client_address, "client_id": client_id, "timestamp": time.time() }) # 检查消息大小 if len(message) > self.message_config["max_message_size"]: print(f"✗ 消息过大,已丢弃: {len(message)} bytes") self.message_stats["messages_dropped"] += 1 return # 如果启用队列,将消息添加到队列中 if self.message_config["enable_message_queue"]: with self.message_queue_lock: if len(self.message_queue) < self.message_config["max_queue_size"]: self.message_queue.append({ "message": message, "client_address": client_address, "client_socket": client_socket, "client_id": client_id }) else: print("✗ 消息队列已满,丢弃消息") self.message_stats["messages_dropped"] += 1 else: # 直接处理消息 self._route_message_internal(message, client_address, client_socket, client_id) except Exception as e: print(f"✗ 消息路由失败: {e}") self.message_stats["errors"] += 1 import traceback traceback.print_exc() def _route_message_internal(self, message: bytes, client_address: tuple, client_socket, client_id: str = None): """ 内部消息路由处理 Args: message: 消息数据 client_address: 客户端地址 client_socket: 客户端套接字 client_id: 客户端ID(可选) """ try: # 解析消息 try: message_str = message.decode('utf-8') message_data = json.loads(message_str) except Exception as e: print(f"✗ 消息解析失败: {e}") self.message_stats["errors"] += 1 return # 获取消息类型 message_type = message_data.get("type", "unknown") # 检查消息过滤 if self.message_config["enable_message_filtering"]: if not self._is_message_allowed(message_type, client_id): print(f"✗ 消息被过滤: {message_type}") return # 查找消息处理器 handler = self.message_handlers.get(message_type) if handler: try: # 调用消息处理器 handler(message_data, client_address, client_socket, client_id) self.message_stats["messages_routed"] += 1 # 触发消息路由回调 self._trigger_message_callback("message_routed", { "message_type": message_type, "client_address": client_address, "client_id": client_id, "timestamp": time.time() }) except Exception as e: print(f"✗ 消息处理器执行失败: {message_type} - {e}") self.message_stats["handler_errors"] += 1 # 触发消息错误回调 self._trigger_message_callback("message_error", { "message_type": message_type, "error": str(e), "client_address": client_address, "client_id": client_id, "timestamp": time.time() }) else: print(f"✗ 未找到消息处理器: {message_type}") self.message_stats["errors"] += 1 except Exception as e: print(f"✗ 内部消息路由处理失败: {e}") self.message_stats["errors"] += 1 def _is_message_allowed(self, message_type: str, client_id: str = None) -> bool: """ 检查消息是否被允许 Args: message_type: 消息类型 client_id: 客户端ID(可选) Returns: 消息是否被允许 """ try: # 检查客户端是否已认证(某些消息类型不需要认证) if message_type not in ["auth", "ping", "pong"]: if not client_id or not self.plugin.client_manager.is_client_authenticated(client_id): return False return True except Exception as e: print(f"✗ 消息允许检查失败: {e}") self.message_stats["errors"] += 1 return False def register_message_handler(self, message_type: str, handler: Callable) -> bool: """ 注册消息处理器 Args: message_type: 消息类型 handler: 处理器函数 Returns: 是否注册成功 """ try: self.message_handlers[message_type] = handler print(f"✓ 消息处理器已注册: {message_type}") return True except Exception as e: print(f"✗ 消息处理器注册失败: {e}") return False def unregister_message_handler(self, message_type: str) -> bool: """ 注销消息处理器 Args: message_type: 消息类型 Returns: 是否注销成功 """ try: if message_type in self.message_handlers: del self.message_handlers[message_type] print(f"✓ 消息处理器已注销: {message_type}") return True else: print(f"✗ 消息处理器不存在: {message_type}") return False except Exception as e: print(f"✗ 消息处理器注销失败: {e}") return False def send_message(self, message_data: Dict[str, Any], client_socket, client_id: str = None) -> bool: """ 发送消息到客户端 Args: message_data: 消息数据 client_socket: 客户端套接字 client_id: 客户端ID(可选) Returns: 是否发送成功 """ try: if not self.enabled: return False # 序列化消息 try: message_str = json.dumps(message_data, ensure_ascii=False) message_bytes = message_str.encode('utf-8') except Exception as e: print(f"✗ 消息序列化失败: {e}") self.message_stats["errors"] += 1 return False # 检查消息大小 if len(message_bytes) > self.message_config["max_message_size"]: print(f"✗ 消息过大,无法发送: {len(message_bytes)} bytes") self.message_stats["messages_dropped"] += 1 return False # 发送消息 try: client_socket.send(message_bytes) except Exception as e: print(f"✗ 消息发送失败: {e}") self.message_stats["errors"] += 1 return False self.message_stats["messages_sent"] += 1 self.message_stats["bytes_sent"] += len(message_bytes) # 更新客户端统计 if client_id: client_data = self.plugin.client_manager.get_client(client_id) if client_data: client_data["messages_sent"] += 1 client_data["bytes_sent"] += len(message_bytes) # 触发消息发送回调 self._trigger_message_callback("message_sent", { "message_type": message_data.get("type", "unknown"), "message_size": len(message_bytes), "client_id": client_id, "timestamp": time.time() }) return True except Exception as e: print(f"✗ 发送消息失败: {e}") self.message_stats["errors"] += 1 return False def broadcast_message(self, message_data: Dict[str, Any], exclude_client_id: str = None) -> bool: """ 广播消息到所有客户端 Args: message_data: 消息数据 exclude_client_id: 要排除的客户端ID(可选) Returns: 是否广播成功 """ try: if not self.enabled or not self.message_config["enable_broadcast"]: return False # 序列化消息 try: message_str = json.dumps(message_data, ensure_ascii=False) message_bytes = message_str.encode('utf-8') except Exception as e: print(f"✗ 广播消息序列化失败: {e}") self.message_stats["errors"] += 1 return False # 检查消息大小 if len(message_bytes) > self.message_config["max_message_size"]: print(f"✗ 广播消息过大,无法发送: {len(message_bytes)} bytes") self.message_stats["messages_dropped"] += 1 return False # 获取所有客户端 clients = self.plugin.client_manager.get_all_clients() success_count = 0 # 发送消息到每个客户端 for client_id, client_data in clients.items(): # 跳过排除的客户端 if client_id == exclude_client_id: continue try: client_data["socket"].send(message_bytes) client_data["messages_sent"] += 1 client_data["bytes_sent"] += len(message_bytes) success_count += 1 except Exception as e: print(f"✗ 广播消息发送失败: {client_id} - {e}") self.message_stats["errors"] += 1 self.message_stats["broadcast_messages"] += 1 self.message_stats["messages_sent"] += success_count self.message_stats["bytes_sent"] += len(message_bytes) * success_count # 触发广播发送回调 self._trigger_message_callback("broadcast_sent", { "message_type": message_data.get("type", "unknown"), "message_size": len(message_bytes), "recipient_count": success_count, "timestamp": time.time() }) return success_count > 0 except Exception as e: print(f"✗ 广播消息失败: {e}") self.message_stats["errors"] += 1 return False # 默认消息处理器 def _handle_ping(self, message_data: Dict[str, Any], client_address: tuple, client_socket, client_id: str = None): """处理ping消息""" try: # 回复pong消息 pong_message = { "type": "pong", "timestamp": time.time(), "ping_id": message_data.get("ping_id", str(uuid.uuid4())) } self.send_message(pong_message, client_socket, client_id) # 更新客户端心跳 if client_id: self.plugin.client_manager.update_client_heartbeat(client_id) except Exception as e: print(f"✗ ping消息处理失败: {e}") self.message_stats["errors"] += 1 def _handle_pong(self, message_data: Dict[str, Any], client_address: tuple, client_socket, client_id: str = None): """处理pong消息""" try: # 可以在这里处理延迟计算等逻辑 pass except Exception as e: print(f"✗ pong消息处理失败: {e}") self.message_stats["errors"] += 1 def _handle_heartbeat(self, message_data: Dict[str, Any], client_address: tuple, client_socket, client_id: str = None): """处理心跳消息""" try: # 更新客户端心跳 if client_id: self.plugin.client_manager.update_client_heartbeat(client_id) except Exception as e: print(f"✗ 心跳消息处理失败: {e}") self.message_stats["errors"] += 1 def _handle_auth(self, message_data: Dict[str, Any], client_address: tuple, client_socket, client_id: str = None): """处理认证消息""" try: if not client_id: print("✗ 认证消息缺少客户端ID") return # 使用客户端管理器进行认证 if self.plugin.client_manager: auth_success = self.plugin.client_manager.authenticate_client(client_id, message_data) if auth_success: # 发送认证成功消息 success_message = { "type": "auth_result", "success": True, "message": "认证成功" } self.send_message(success_message, client_socket, client_id) else: # 发送认证失败消息 fail_message = { "type": "auth_result", "success": False, "message": "认证失败" } self.send_message(fail_message, client_socket, client_id) except Exception as e: print(f"✗ 认证消息处理失败: {e}") self.message_stats["errors"] += 1 def _handle_chat(self, message_data: Dict[str, Any], client_address: tuple, client_socket, client_id: str = None): """处理聊天消息""" try: # 广播聊天消息到所有客户端 chat_message = { "type": "chat", "sender": message_data.get("sender", "unknown"), "message": message_data.get("message", ""), "timestamp": time.time() } self.broadcast_message(chat_message, exclude_client_id=client_id) except Exception as e: print(f"✗ 聊天消息处理失败: {e}") self.message_stats["errors"] += 1 def _handle_join_room(self, message_data: Dict[str, Any], client_address: tuple, client_socket, client_id: str = None): """处理加入房间消息""" try: room_id = message_data.get("room_id") if not room_id: print("✗ 加入房间消息缺少房间ID") return # 使用房间管理器处理加入房间请求 if self.plugin.room_manager: join_success = self.plugin.room_manager.add_client_to_room(room_id, client_id) if join_success: # 发送加入成功消息 success_message = { "type": "join_room_result", "success": True, "room_id": room_id, "message": "成功加入房间" } self.send_message(success_message, client_socket, client_id) # 通知房间内其他客户端 notification = { "type": "client_joined_room", "client_id": client_id, "room_id": room_id } self.plugin.room_manager.broadcast_to_room(room_id, notification, exclude_client_id=client_id) else: # 发送加入失败消息 fail_message = { "type": "join_room_result", "success": False, "room_id": room_id, "message": "加入房间失败" } self.send_message(fail_message, client_socket, client_id) except Exception as e: print(f"✗ 加入房间消息处理失败: {e}") self.message_stats["errors"] += 1 def _handle_leave_room(self, message_data: Dict[str, Any], client_address: tuple, client_socket, client_id: str = None): """处理离开房间消息""" try: room_id = message_data.get("room_id") if not room_id: print("✗ 离开房间消息缺少房间ID") return # 使用房间管理器处理离开房间请求 if self.plugin.room_manager: leave_success = self.plugin.room_manager.remove_client_from_room(room_id, client_id) if leave_success: # 发送离开成功消息 success_message = { "type": "leave_room_result", "success": True, "room_id": room_id, "message": "成功离开房间" } self.send_message(success_message, client_socket, client_id) # 通知房间内其他客户端 notification = { "type": "client_left_room", "client_id": client_id, "room_id": room_id } self.plugin.room_manager.broadcast_to_room(room_id, notification, exclude_client_id=client_id) except Exception as e: print(f"✗ 离开房间消息处理失败: {e}") self.message_stats["errors"] += 1 def _handle_sync_data(self, message_data: Dict[str, Any], client_address: tuple, client_socket, client_id: str = None): """处理同步数据消息""" try: # 将同步数据广播到房间内的其他客户端 room_id = message_data.get("room_id") if room_id and self.plugin.room_manager: # 移除房间ID,避免重复处理 sync_data = message_data.copy() sync_data.pop("room_id", None) self.plugin.room_manager.broadcast_to_room(room_id, sync_data, exclude_client_id=client_id) except Exception as e: print(f"✗ 同步数据消息处理失败: {e}") self.message_stats["errors"] += 1 def get_message_stats(self) -> Dict[str, Any]: """ 获取消息统计信息 Returns: 消息统计字典 """ return { "stats": self.message_stats.copy(), "config": self.message_config.copy(), "handlers_count": len(self.message_handlers), "queue_size": len(self.message_queue) } def reset_stats(self): """重置消息统计信息""" try: self.message_stats = { "messages_received": 0, "messages_sent": 0, "messages_routed": 0, "messages_dropped": 0, "broadcast_messages": 0, "handler_errors": 0, "bytes_received": 0, "bytes_sent": 0, "errors": 0 } print("✓ 消息统计信息已重置") except Exception as e: print(f"✗ 消息统计信息重置失败: {e}") def set_message_config(self, config: Dict[str, Any]) -> bool: """ 设置消息配置 Args: config: 消息配置字典 Returns: 是否设置成功 """ try: self.message_config.update(config) print(f"✓ 消息配置已更新: {self.message_config}") return True except Exception as e: print(f"✗ 消息配置设置失败: {e}") return False def get_message_config(self) -> Dict[str, Any]: """ 获取消息配置 Returns: 消息配置字典 """ return self.message_config.copy() def _trigger_message_callback(self, callback_type: str, data: Dict[str, Any]): """ 触发消息回调 Args: callback_type: 回调类型 data: 回调数据 """ try: if callback_type in self.message_callbacks: for callback in self.message_callbacks[callback_type]: try: callback(data) except Exception as e: print(f"✗ 消息回调执行失败: {callback_type} - {e}") except Exception as e: print(f"✗ 消息回调触发失败: {e}") def register_message_callback(self, callback_type: str, callback: callable): """ 注册消息回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.message_callbacks: self.message_callbacks[callback_type].append(callback) print(f"✓ 消息回调已注册: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 消息回调注册失败: {e}") def unregister_message_callback(self, callback_type: str, callback: callable): """ 注销消息回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.message_callbacks: if callback in self.message_callbacks[callback_type]: self.message_callbacks[callback_type].remove(callback) print(f"✓ 消息回调已注销: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 消息回调注销失败: {e}")