socketserver 原始碼閱讀
首先看到檔案上半部分的註釋,講清楚了這個module裡的類繼承關係。
+------------+ | BaseServer | +------------+ | v +-----------++------------------+ | TCPServer |------->| UnixStreamServer | +-----------++------------------+ | v +-----------++--------------------+ | UDPServer |------->| UnixDatagramServer | +-----------++--------------------+
不在上面描述的有執行緒和程序模型,它們是通過Mixin實現的。一個同步的伺服器基本上 就是以下這樣的套路:
import socket sock = socket.socket() sock.bind(('localhost', 8080)) sock.listen() def handle(conn, client_addr): conn.send(b"some data") conn.close() while True: conn, client_addr = sock.accept() handle(conn, client_addr)
socketserver 也不例外,雖然裡面用到了selectors.PollSelector
,這個檔案裡最精彩
的部分在於實現ThreadingMixIn
和ForkingMixIn
。我也來寫一個更簡單的版本:
import socket import threading import selectors class BaseServer: def __init__(self): self.selector = selectors.PollSelector() def fileno(self): raise NotImplemented() def handle_request(self): raise NotImplemented() def serve_forever(self): self.selector.register(self, selectors.EVENT_READ) while True: if self.selector.select(): self.handle_request() class TCPServer(BaseServer): def __init__(self): super().__init__() self.socket = socket.socket() self.socket.bind(('localhost', 8080)) self.socket.listen() def fileno(self): return self.socket.fileno() def handle_request(self): return self.__handle_request() def _handle_request(self): conn, addr = self.socket.accept() conn.send(b'hello world\n') conn.close() class ThreadingMixIn: def handle_request(self): t = threading.Thread( target=self._handle_request, ) t.start() class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass if __name__ == "__main__": # TCPServer().serve_forever() ThreadingTCPServer().serve_forever()