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 + -
显示快捷键?