socketserver.py

来自「mallet是自然语言处理、机器学习领域的一个开源项目。」· Python 代码 · 共 577 行 · 第 1/2 页

PY
577
字号
    - get_request() -> request, client_address    - verify_request(request, client_address)    - process_request(request, client_address)    - close_request(request)    - handle_error()    Methods for derived classes:    - finish_request(request, client_address)    Class variables that may be overridden by derived classes or    instances:    - address_family    - socket_type    - request_queue_size (only for stream sockets)    - reuse_address    Instance variables:    - server_address    - RequestHandlerClass    - socket    """    address_family = socket.AF_INET    socket_type = socket.SOCK_STREAM    request_queue_size = 5    allow_reuse_address = 0    def __init__(self, server_address, RequestHandlerClass):        """Constructor.  May be extended, do not override."""        BaseServer.__init__(self, server_address, RequestHandlerClass)        self.socket = socket.socket(self.address_family,                                    self.socket_type)        self.server_bind()        self.server_activate()    def server_bind(self):        """Called by constructor to bind the socket.        May be overridden.        """        if self.allow_reuse_address:            self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)        self.socket.bind(self.server_address)    def server_activate(self):        """Called by constructor to activate the server.        May be overridden.        """        self.socket.listen(self.request_queue_size)    def server_close(self):        """Called to clean-up the server.        May be overridden.        """        self.socket.close()    def fileno(self):        """Return socket file number.        Interface required by select().        """        return self.socket.fileno()    def get_request(self):        """Get the request and client address from the socket.        May be overridden.        """        return self.socket.accept()    def close_request(self, request):        """Called to clean up an individual request."""        request.close()class UDPServer(TCPServer):    """UDP server class."""    allow_reuse_address = 0    socket_type = socket.SOCK_DGRAM    max_packet_size = 8192    def get_request(self):        data, client_addr = self.socket.recvfrom(self.max_packet_size)        return (data, self.socket), client_addr    def server_activate(self):        # No need to call listen() for UDP.        pass    def close_request(self, request):        # No need to close anything.        passclass ForkingMixIn:    """Mix-in class to handle each request in a new process."""    active_children = None    max_children = 40    def collect_children(self):        """Internal routine to wait for died children."""        while self.active_children:            if len(self.active_children) < self.max_children:                options = os.WNOHANG            else:                # If the maximum number of children are already                # running, block while waiting for a child to exit                options = 0            try:                pid, status = os.waitpid(0, options)            except os.error:                pid = None            if not pid: break            self.active_children.remove(pid)    def process_request(self, request, client_address):        """Fork a new subprocess to process the request."""        self.collect_children()        pid = os.fork()        if pid:            # Parent process            if self.active_children is None:                self.active_children = []            self.active_children.append(pid)            self.close_request(request)            return        else:            # Child process.            # This must never return, hence os._exit()!            try:                self.finish_request(request, client_address)                os._exit(0)            except:                try:                    self.handle_error(request, client_address)                finally:                    os._exit(1)class ThreadingMixIn:    """Mix-in class to handle each request in a new thread."""    def process_request_thread(self, request, client_address):        """Same as in BaseServer but as a thread.        In addition, exception handling is done here.        """        try:            self.finish_request(request, client_address)            self.close_request(request)        except:            self.handle_error(request, client_address)            self.close_request(request)    def process_request(self, request, client_address):        """Start a new thread to process the request."""        import threading        t = threading.Thread(target = self.process_request_thread,                             args = (request, client_address))        t.start()class ForkingUDPServer(ForkingMixIn, UDPServer): passclass ForkingTCPServer(ForkingMixIn, TCPServer): passclass ThreadingUDPServer(ThreadingMixIn, UDPServer): passclass ThreadingTCPServer(ThreadingMixIn, TCPServer): passif hasattr(socket, 'AF_UNIX'):    class UnixStreamServer(TCPServer):        address_family = socket.AF_UNIX    class UnixDatagramServer(UDPServer):        address_family = socket.AF_UNIX    class ThreadingUnixStreamServer(ThreadingMixIn, UnixStreamServer): pass    class ThreadingUnixDatagramServer(ThreadingMixIn, UnixDatagramServer): passclass BaseRequestHandler:    """Base class for request handler classes.    This class is instantiated for each request to be handled.  The    constructor sets the instance variables request, client_address    and server, and then calls the handle() method.  To implement a    specific service, all you need to do is to derive a class which    defines a handle() method.    The handle() method can find the request as self.request, the    client address as self.client_address, and the server (in case it    needs access to per-server information) as self.server.  Since a    separate instance is created for each request, the handle() method    can define arbitrary other instance variariables.    """    def __init__(self, request, client_address, server):        self.request = request        self.client_address = client_address        self.server = server        try:            self.setup()            self.handle()            self.finish()        finally:            sys.exc_traceback = None    # Help garbage collection    def setup(self):        pass    def handle(self):        pass    def finish(self):        pass# The following two classes make it possible to use the same service# class for stream or datagram servers.# Each class sets up these instance variables:# - rfile: a file object from which receives the request is read# - wfile: a file object to which the reply is written# When the handle() method returns, wfile is flushed properlyclass StreamRequestHandler(BaseRequestHandler):    """Define self.rfile and self.wfile for stream sockets."""    # Default buffer sizes for rfile, wfile.    # We default rfile to buffered because otherwise it could be    # really slow for large data (a getc() call per byte); we make    # wfile unbuffered because (a) often after a write() we want to    # read and we need to flush the line; (b) big writes to unbuffered    # files are typically optimized by stdio even when big reads    # aren't.    rbufsize = -1    wbufsize = 0    def setup(self):        self.connection = self.request        self.rfile = self.connection.makefile('rb', self.rbufsize)        self.wfile = self.connection.makefile('wb', self.wbufsize)    def finish(self):        self.wfile.flush()        self.wfile.close()        self.rfile.close()class DatagramRequestHandler(BaseRequestHandler):    # XXX Regrettably, I cannot get this working on Linux;    # s.recvfrom() doesn't return a meaningful client address.    """Define self.rfile and self.wfile for datagram sockets."""    def setup(self):        import StringIO        self.packet, self.socket = self.request        self.rfile = StringIO.StringIO(self.packet)        self.wfile = StringIO.StringIO()    def finish(self):        self.socket.sendto(self.wfile.getvalue(), self.client_address)

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?