""" 连接管理器模块 负责管理网络连接和客户端状态 """ import time from typing import Dict, Any, List, Optional import threading import socket class ConnectionManager: """ 连接管理器 负责管理网络连接和客户端状态 """ def __init__(self, plugin): """ 初始化连接管理器 Args: plugin: 网络同步插件实例 """ self.plugin = plugin self.enabled = False self.initialized = False # 连接配置 self.connection_config = { 'max_connections': 32, 'connection_timeout': 30.0, 'reconnect_attempts': 3, 'reconnect_interval': 5.0, 'heartbeat_interval': 5.0, 'enable_auto_reconnect': True, 'enable_connection_limits': True, 'max_connections_per_ip': 5 } # 客户端管理 self.clients = {} # 已连接的客户端 self.pending_connections = {} # 待处理的连接 self.banned_ips = set() # 被禁止的IP地址 # 服务器状态 self.server_state = { 'is_running': False, 'port': 7777, 'clients_connected': 0, 'peak_connections': 0, 'bytes_sent': 0, 'bytes_received': 0 } # 客户端状态 self.client_state = { 'is_connected': False, 'server_address': '', 'server_port': 7777, 'connection_time': 0.0, 'last_heartbeat': 0.0, 'reconnect_attempts': 0 } # 连接统计 self.connection_stats = { 'connections_accepted': 0, 'connections_rejected': 0, 'connections_lost': 0, 'connections_timed_out': 0, 'reconnections': 0, 'banned_connections': 0 } # 线程管理 self.connection_thread = None self.heartbeat_thread = None self.reconnect_thread = None self.running = False # 回调函数 self.connection_callbacks = { 'client_connected': [], 'client_disconnected': [], 'connection_timeout': [], 'reconnect_attempt': [], 'connection_banned': [] } # 时间戳记录 self.last_connection_check = 0.0 self.last_heartbeat_check = 0.0 self.last_reconnect_attempt = 0.0 print("✓ 连接管理器已创建") def initialize(self) -> bool: """ 初始化连接管理器 Returns: 是否初始化成功 """ try: self.initialized = True print("✓ 连接管理器初始化完成") return True except Exception as e: print(f"✗ 连接管理器初始化失败: {e}") import traceback traceback.print_exc() return False def enable(self) -> bool: """ 启用连接管理器 Returns: 是否启用成功 """ try: if not self.initialized: print("✗ 连接管理器未初始化") return False self.enabled = True self.running = True print("✓ 连接管理器已启用") return True except Exception as e: print(f"✗ 连接管理器启用失败: {e}") import traceback traceback.print_exc() return False def disable(self): """禁用连接管理器""" try: self.enabled = False self.running = False # 断开所有连接 self._disconnect_all_clients() self._disconnect_from_server() print("✓ 连接管理器已禁用") except Exception as e: print(f"✗ 连接管理器禁用失败: {e}") import traceback traceback.print_exc() def finalize(self): """清理连接管理器资源""" try: self.disable() self.clients.clear() self.pending_connections.clear() self.banned_ips.clear() self.connection_callbacks.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() # 检查连接超时 if current_time - self.last_connection_check >= 1.0: # 每秒检查一次 self._check_connection_timeouts(current_time) self.last_connection_check = current_time # 检查心跳超时 if current_time - self.last_heartbeat_check >= self.connection_config['heartbeat_interval']: self._check_heartbeat_timeouts(current_time) self.last_heartbeat_check = current_time except Exception as e: print(f"✗ 连接管理器更新失败: {e}") import traceback traceback.print_exc() def _check_connection_timeouts(self, current_time: float): """ 检查连接超时 Args: current_time: 当前时间 """ try: timeout_clients = [] for client_id, client_data in self.clients.items(): connect_time = client_data.get('connect_time', 0) if current_time - connect_time > self.connection_config['connection_timeout']: timeout_clients.append(client_id) for client_id in timeout_clients: self._disconnect_client(client_id, "timeout") self.connection_stats['connections_timed_out'] += 1 # 触发连接超时回调 self._trigger_connection_callback('connection_timeout', { 'client_id': client_id, 'reason': 'timeout' }) except Exception as e: print(f"✗ 连接超时检查失败: {e}") def _check_heartbeat_timeouts(self, current_time: float): """ 检查心跳超时 Args: current_time: 当前时间 """ try: timeout_clients = [] for client_id, client_data in self.clients.items(): last_heartbeat = client_data.get('last_heartbeat', 0) if current_time - last_heartbeat > self.connection_config['heartbeat_interval'] * 3: timeout_clients.append(client_id) for client_id in timeout_clients: self._disconnect_client(client_id, "heartbeat_timeout") except Exception as e: print(f"✗ 心跳超时检查失败: {e}") def connect_to_server(self, host: str, port: int = None) -> bool: """ 连接到服务器 Args: host: 服务器地址 port: 服务器端口 Returns: 是否连接成功 """ try: if self.client_state['is_connected']: print("✗ 客户端已连接到服务器") return False if port is None: port = self.connection_config['server_port'] # 更新客户端状态 self.client_state['server_address'] = host self.client_state['server_port'] = port self.client_state['connection_time'] = time.time() self.client_state['reconnect_attempts'] = 0 # 通过网络管理器连接 if self.plugin.network_manager: success = self.plugin.network_manager.connect_to_server(host, port) if success: self.client_state['is_connected'] = True print(f"✓ 已连接到服务器: {host}:{port}") return True else: print("✗ 连接服务器失败") return False else: print("✗ 网络管理器未初始化") return False except Exception as e: print(f"✗ 连接服务器失败: {e}") import traceback traceback.print_exc() return False def disconnect_from_server(self): """断开与服务器的连接""" try: self._disconnect_from_server() print("✓ 已断开与服务器的连接") except Exception as e: print(f"✗ 断开服务器连接失败: {e}") def _disconnect_from_server(self): """内部方法:断开与服务器的连接""" try: if self.plugin.network_manager: self.plugin.network_manager.disconnect_client() self.client_state['is_connected'] = False self.client_state['server_address'] = '' self.client_state['connection_time'] = 0.0 except Exception as e: print(f"✗ 服务器断开连接失败: {e}") def add_client(self, client_id: str, client_socket: socket.socket, client_address: tuple) -> bool: """ 添加客户端连接 Args: client_id: 客户端ID client_socket: 客户端套接字 client_address: 客户端地址 Returns: 是否添加成功 """ try: client_ip = client_address[0] # 检查IP是否被禁止 if client_ip in self.banned_ips: self.connection_stats['banned_connections'] += 1 client_socket.close() # 触发连接禁止回调 self._trigger_connection_callback('connection_banned', { 'client_id': client_id, 'ip': client_ip, 'address': client_address }) return False # 检查连接限制 if self.connection_config['enable_connection_limits']: ip_connections = sum(1 for client in self.clients.values() if client.get('address', ('', 0))[0] == client_ip) if ip_connections >= self.connection_config['max_connections_per_ip']: self.connection_stats['connections_rejected'] += 1 client_socket.close() return False # 检查最大连接数 if (self.connection_config['enable_connection_limits'] and len(self.clients) >= self.connection_config['max_connections']): self.connection_stats['connections_rejected'] += 1 client_socket.close() return False # 添加客户端 self.clients[client_id] = { 'socket': client_socket, 'address': client_address, 'connect_time': time.time(), 'last_heartbeat': time.time(), 'bytes_sent': 0, 'bytes_received': 0, 'ping': 0.0 } # 更新服务器状态 self.server_state['clients_connected'] = len(self.clients) if len(self.clients) > self.server_state['peak_connections']: self.server_state['peak_connections'] = len(self.clients) self.connection_stats['connections_accepted'] += 1 # 触发客户端连接回调 self._trigger_connection_callback('client_connected', { 'client_id': client_id, 'address': client_address }) print(f"✓ 客户端已连接: {client_id} ({client_address})") return True except Exception as e: print(f"✗ 添加客户端失败: {e}") self.connection_stats['connections_rejected'] += 1 return False def remove_client(self, client_id: str, reason: str = "unknown"): """ 移除客户端连接 Args: client_id: 客户端ID reason: 断开原因 """ try: if client_id in self.clients: client_data = self.clients[client_id] # 关闭套接字 try: client_data['socket'].close() except Exception as e: pass # 移除客户端 del self.clients[client_id] # 更新服务器状态 self.server_state['clients_connected'] = len(self.clients) self.connection_stats['connections_lost'] += 1 # 触发客户端断开连接回调 self._trigger_connection_callback('client_disconnected', { 'client_id': client_id, 'reason': reason }) print(f"✓ 客户端已断开: {client_id} (原因: {reason})") except Exception as e: print(f"✗ 移除客户端失败: {e}") def _disconnect_client(self, client_id: str, reason: str = "unknown"): """ 断开客户端连接 Args: client_id: 客户端ID reason: 断开原因 """ self.remove_client(client_id, reason) def _disconnect_all_clients(self): """断开所有客户端连接""" try: client_ids = list(self.clients.keys()) for client_id in client_ids: self._disconnect_client(client_id, "server_shutdown") except Exception as e: print(f"✗ 断开所有客户端连接失败: {e}") def send_heartbeat(self, client_id: str = None): """ 发送心跳包 Args: client_id: 客户端ID(None表示服务器发送给所有客户端) """ try: heartbeat_data = { 'timestamp': time.time() } if client_id: # 发送给特定客户端 if self.plugin.protocol_handler: self.plugin.protocol_handler.send_message('HEARTBEAT', heartbeat_data, client_id) else: # 发送给所有客户端 if self.plugin.protocol_handler: for cid in self.clients.keys(): self.plugin.protocol_handler.send_message('HEARTBEAT', heartbeat_data, cid) except Exception as e: print(f"✗ 心跳包发送失败: {e}") def handle_heartbeat(self, client_id: str, data: Dict[str, Any]): """ 处理心跳包 Args: client_id: 客户端ID data: 心跳数据 """ try: if client_id in self.clients: self.clients[client_id]['last_heartbeat'] = time.time() self.clients[client_id]['ping'] = time.time() - data.get('timestamp', time.time()) except Exception as e: print(f"✗ 心跳包处理失败: {e}") def ban_ip(self, ip_address: str): """ 禁止IP地址 Args: ip_address: IP地址 """ try: self.banned_ips.add(ip_address) print(f"✓ IP地址已被禁止: {ip_address}") # 断开该IP的所有连接 clients_to_disconnect = [ client_id for client_id, client_data in self.clients.items() if client_data.get('address', ('', 0))[0] == ip_address ] for client_id in clients_to_disconnect: self._disconnect_client(client_id, "banned") except Exception as e: print(f"✗ IP禁止失败: {e}") def unban_ip(self, ip_address: str): """ 解除IP地址禁止 Args: ip_address: IP地址 """ try: if ip_address in self.banned_ips: self.banned_ips.remove(ip_address) print(f"✓ IP地址禁止已解除: {ip_address}") except Exception as e: print(f"✗ IP解除禁止失败: {e}") def get_clients(self) -> Dict[str, Any]: """ 获取所有客户端信息 Returns: 客户端信息字典 """ try: return {k: v.copy() for k, v in self.clients.items()} except Exception as e: print(f"✗ 客户端信息获取失败: {e}") return {} def get_client_count(self) -> int: """ 获取客户端数量 Returns: 客户端数量 """ return len(self.clients) def get_banned_ips(self) -> List[str]: """ 获取被禁止的IP地址列表 Returns: 被禁止的IP地址列表 """ return list(self.banned_ips) def is_client_connected(self, client_id: str) -> bool: """ 检查客户端是否连接 Args: client_id: 客户端ID Returns: 客户端是否连接 """ return client_id in self.clients def get_server_state(self) -> Dict[str, Any]: """ 获取服务器状态 Returns: 服务器状态字典 """ return self.server_state.copy() def get_client_state(self) -> Dict[str, Any]: """ 获取客户端状态 Returns: 客户端状态字典 """ return self.client_state.copy() def get_connection_stats(self) -> Dict[str, Any]: """ 获取连接统计信息 Returns: 连接统计字典 """ return self.connection_stats.copy() def reset_connection_stats(self): """重置连接统计信息""" try: self.connection_stats = { 'connections_accepted': 0, 'connections_rejected': 0, 'connections_lost': 0, 'connections_timed_out': 0, 'reconnections': 0, 'banned_connections': 0 } print("✓ 连接统计信息已重置") except Exception as e: print(f"✗ 连接统计信息重置失败: {e}") def set_connection_config(self, config: Dict[str, Any]) -> bool: """ 设置连接配置 Args: config: 连接配置字典 Returns: 是否设置成功 """ try: self.connection_config.update(config) print(f"✓ 连接配置已更新: {self.connection_config}") return True except Exception as e: print(f"✗ 连接配置设置失败: {e}") return False def get_connection_config(self) -> Dict[str, Any]: """ 获取连接配置 Returns: 连接配置字典 """ return self.connection_config.copy() def _trigger_connection_callback(self, callback_type: str, data: Dict[str, Any]): """ 触发连接回调 Args: callback_type: 回调类型 data: 回调数据 """ try: if callback_type in self.connection_callbacks: for callback in self.connection_callbacks[callback_type]: try: callback(data) except Exception as e: print(f"✗ 连接回调执行失败: {e}") except Exception as e: print(f"✗ 连接回调触发失败: {e}") def register_connection_callback(self, callback_type: str, callback: callable): """ 注册连接回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.connection_callbacks: self.connection_callbacks[callback_type].append(callback) print(f"✓ 连接回调已注册: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 连接回调注册失败: {e}") def unregister_connection_callback(self, callback_type: str, callback: callable): """ 注销连接回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.connection_callbacks: if callback in self.connection_callbacks[callback_type]: self.connection_callbacks[callback_type].remove(callback) print(f"✓ 连接回调已注销: {callback_type}") except Exception as e: print(f"✗ 连接回调注销失败: {e}")