import socket import signal import threading from concurrent.futures import ThreadPoolExecutor from config.setting import settings from model.index import UNKNOWN_MESSAGE from processor.tcp_processor import TcpMessageProcessor from config.logger_config import logger class TCPServer: def __init__(self): self.host = settings.host self.port = settings.port self.max_workers = settings.max_workers self.timeout = settings.timeout self.server_socket = None self.running = False self.thread_pool = ThreadPoolExecutor(max_workers=self.max_workers) self.message_processor = TcpMessageProcessor() # 已经连接的客户端 self.clients = {} self.client_lock = threading.Lock() self.server_thread = None signal.signal(signal.SIGTERM, self._handle_signal) signal.signal(signal.SIGINT, self._handle_signal) def _handle_signal(self, signum, frame): """处理终止信号,触发优雅关闭""" logger.info(f"收到信号 {signum},准备关闭服务器...") self.running = False def _start_loop(self): """启动服务器""" try: self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server_socket.bind((self.host, self.port)) self.server_socket.listen(5) self.server_socket.settimeout(1.0) self.running = True logger.info(f"TCP服务器启动,监听 {self.host}:{self.port} " f"(最大线程: {self.max_workers}, 超时: {self.timeout}s)") while self.running: try: client_socket, client_address = self.server_socket.accept() client_ip = client_address[0] client_socket.settimeout(self.timeout) logger.info(f"新连接: {client_address}") # 存储客户端 with self.client_lock: self.clients[client_ip] = client_socket # 提交到线程池处理 self.thread_pool.submit(self.handle_client, client_socket, client_ip) except socket.timeout: continue except Exception as e: if self.running: logger.error(f"接受连接失败: {str(e)}") except Exception as e: logger.error(f"TCP服务器启动失败: {str(e)}") finally: self.stop() def start(self): self.server_thread = threading.Thread(target=self._start_loop, daemon=True) self.server_thread.start() def stop(self): if not self.running: return self.running = False logger.info("开始关闭服务器...") # 移除客户端 with self.client_lock: for client_socket in self.clients.values(): try: client_socket.close() except Exception as e: logger.warning(f"关闭客户端连接失败: {str(e)}") self.clients.clear() # 关闭线程池 self.thread_pool.shutdown(wait=True) logger.info("所有客户端处理线程已结束") # 关闭连接 if self.server_socket: self.server_socket.close() logger.info(f"服务器已关闭({self.host}:{self.port})") def handle_client(self, client_socket, client_ip): """处理客户端连接""" try: while True: data = client_socket.recv(1024) if not data: logger.info(f"客户端 {client_ip} 主动断开连接") break message = data.decode('utf-8').strip() logger.info(f"收到 {client_ip} 的消息: {message}") # 放到消息处理器里面处理 response = self.message_processor.process(message) # 回复消息 if response != UNKNOWN_MESSAGE: client_socket.sendall(response.encode('utf-8')) logger.info(f"回复 {client_ip}: {response}") except socket.timeout: logger.warning(f"客户端 {client_ip} 超时未活动") except Exception as e: logger.error(f"处理 {client_ip} 出错: {str(e)}") finally: # 异常情况下关闭连接 with self.client_lock: if client_ip in self.clients: del self.clients[client_ip] try: client_socket.close() logger.info(f"客户端 {client_ip} 连接已关闭") except Exception as e: logger.warning(f"关闭 {client_ip} 连接失败: {str(e)}") def send_to_client(self, client_ip, message): # 先获取客户端连接(加锁保护) with self.client_lock: client_socket = self.clients.get(client_ip) if not client_socket: logger.warning(f"客户端 {client_ip} 不存在或已断开连接") return False # 发送消息 try: client_socket.sendall(message.encode('utf-8')) logger.info(f"主动发送消息给 {client_ip}: {message}") return True except Exception as e: logger.error(f"向 {client_ip} 发送消息失败: {str(e)}") # 发送失败时移除无效连接 with self.client_lock: if client_ip in self.clients: del self.clients[client_ip] return False tcp_server = TCPServer()