class NetworkServerBase: def __init__(self, port): self.host = "0.0.0.0" self.port = port self.server_fd = None self.state = config.SERVER_STOP self.logger = Log() def _close_fd(self): try: self.server_fd.shutdown(socket.SHUT_RDWR) self.server_fd.close() except IOError as e: self.logger.error("net socket close fail err: " + str(e.errno) + " " + e.strerror) def _network_start(self): self.server_fd = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server_fd.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) try: self.server_fd.bind((self.host, self.port)) except IOError as e: self._close_fd() self.logger.error("server bind fail. msg: " + str(e.errno) + " " + e.strerror) return self.server_fd.listen(config.MAX_LISTEN_QUEUE_SIZE) self.server_fd.setblocking(False) self.port = self.server_fd.getsockname()[1] self.state = config.SERVER_ESTABLISHED self.logger.info("server established. port:" + str(self.port))
class WorkerPool: def __init__(self, mode=None): self.mode = mode # 默认使用单进程单线程模式 self.logger = Log() self.conn_pool = None # key = id, value = FunctionHandler. int 到函数的映射 self.handler_dict = {} # 通用工具集 self.common_tools = CommonTools() # 多进程 删掉了 并没有什么用 self.process_count = 1 self.process_pool = None # 单进程模式下处理完的事件丢到这里,后面主循环处理发回客户端 self.response_queue = [] self.auto_incr = 0 def init(self, conn_pool, process_count=4): self.conn_pool = conn_pool if process_count < 1 or process_count > 10: process_count = 1 self.process_count = process_count def start(self): self.common_tools.init(self.handler_dict) self.logger.info("worker pool. light mode") self.logger.info("work process start success") def stop(self): pass def add_handler(self, handler, controller): if isinstance(handler, int) and isinstance(controller, FunctionHandler): self.handler_dict[handler] = controller def del_handler(self, handler): if handler in self.handler_dict.keys(): del self.handler_dict[handler] # 在框架IO层,处理好 [消息] 后调用. # 需要路由到具体逻辑代码 # 最后调用 self.conn_pool.send_event(conn_id, res), res 会在合适的时候发给客户端 def message_handler(self, conn_id, msg): req = Request(conn_id, msg) res = Response(conn_id) handler = req.get_handler() if handler in self.handler_dict.keys(): # 根据 request 哈希到具体函数 self.handler_dict[handler].run(self.common_tools, req, res) for v in res.msg_queue: if isinstance(v, Response): v.pack_buffer(req.msg.get_handler()) v.msg.encryption() self.response_queue.append(v) res.msg_queue = [] self.response_queue.append(res) def update(self): self.common_tools.update() self.message_consumer() # 消费处理好的 response,发向客户端 def message_consumer(self): if len(self.response_queue): res = self.response_queue[0] self.response_queue = self.response_queue[1:] self.conn_pool.send_handler(res.conn_id, res.msg)
class Server: def __init__(self, name, uuid): self.os_name = platform.system() self.python_version = platform.python_version().split(".")[0] self.server_name = name self.server_id = uuid self.network_server = None self.work_process = None self.logger = Log() self.conf_loader = ConfigLoader() def add_handler(self, handler_func): try: self.work_process.add_handler(handler_func.handler_id, handler_func) self.logger.info("add handler " + str(handler_func.handler_id)) except Exception as e: self.logger.error("work process not init." + e.message) # 预选择服务器IO模式 epoll有bug,连接无法安全断开. select实测没light快 囧。。。 def pre_bind_io_mode(self, port, mode): if not isinstance(mode, str): return False if mode.__eq__("epoll") and hasattr(select, 'epoll'): self.network_server = Epoll(port) self.logger.info("network mode epoll") return True if mode.__eq__("epoll_et") and hasattr(select, 'epoll'): self.network_server = Epoll(port, use_et=True) self.logger.info("network mode epoll et") return True if mode.__eq__("select") and hasattr(select, 'select'): self.network_server = Select(port) self.logger.info("network mode select") return True if mode.__eq__("light"): self.network_server = LightServer(port) self.logger.info("network mode light server") return True return False def start(self, port=None, mode=None): if port is None: port = self.conf_loader.get_int("port", 0) if not self.pre_bind_io_mode(port, mode): if hasattr(select, 'epoll'): self.network_server = Epoll(port) self.logger.info("network mode epoll lt") elif hasattr(select, 'select'): self.network_server = Select(port) self.logger.info("network mode select") else: self.network_server = LightServer(port) self.logger.info("network mode light server") self.work_process = WorkerPool(mode="light") # light, multi self.network_server.init(self.work_process) self.work_process.init(self.network_server.conn_pool, 4) self.network_server.start() def run(self): if self.network_server is None: self.logger.error("server instance is None") return if self.network_server.state == SERVER_ESTABLISHED: self.work_process.start() self.network_server.run() def stop(self): self.work_process.stop()