예제 #1
0
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))
예제 #2
0
class Connection:
    err_d = (errno.EINPROGRESS, errno.EALREADY, errno.EWOULDBLOCK)
    err_conn = (errno.EISCONN, 10057, 10035)  # client 10053

    def __init__(self, workers):
        self.client_fd = None
        self.recv_buf = ''
        self.send_buf = ''
        self.conn_id = None
        self.msg = Message()
        self.logger = Log()
        self.workers = workers

    def close_fd(self):
        try:
            self.logger.debug(
                "client exit. fd = " + str(self.client_fd) + "port = " + str(self.client_fd.getpeername()[1]))
            self.client_fd.shutdown(socket.SHUT_RDWR)
            self.client_fd.close()
        except IOError as err:
            self.logger.error("conn socket close fail err:" + str(err.errno))

    def assign(self, fd, conn_id):
        self.client_fd = fd
        self.client_fd.setblocking(False)
        self.client_fd.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
        self.conn_id = conn_id
        self.logger.debug("new client. fd = " + str(self.client_fd) + "port = " + str(self.client_fd.getpeername()[1]))

    def _package_message(self):
        while len(self.recv_buf) != 0:
            size = self.msg.recv(self.recv_buf)
            self.recv_buf = self.recv_buf[size:]
            if self.msg.finish():
                # self.logger.debug("recv msg:" + self.msg.__str__())
                # print "recv msg:" + self.msg.__str__()
                self.workers.message_handler(self.conn_id, self.msg)
                self.msg.assign()

    def recv_event(self):
        text = ''
        # 客户端退出 not text为 True,这里text上空字符串。
        # 如果是客户端暂时没有数据,并不会导致text为空传,导致10035异常,非阻塞模式中
        try:
            text = self.client_fd.recv(1024)
            if not text:
                err_code = 10000
                self.close_fd()
                return True
        except socket.error, (code, strerror):
            if code not in Connection.err_d:
                err_code = code
                self.close_fd()
                return True
        self.recv_buf += text
        self._package_message()
        return False
예제 #3
0
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()