SocketServer这个模块中定义的类比较多,但是设计比较清晰,我们以TCPServer为主线分析,先脉络再细节。
总体脉络
将相关类分为两组,如图:
服务器相关(上)
BaseServer是server基础类,定义server的基本处理运行与request处理机制,TCPServer直接继承它。
Request处理类RequestHandler(下)
BaseRequestHandler是request处理的基础类,TCPServer的request处理类StreamRequestHandler直接继承它。
TCPServer设计细节
从类的设计上说,这里可以说时mixin的最佳实践了,什么是mixin?如何使用mixin?
A mixin is a special kind of multiple inheritance. There are two main situations where mixins are used:
1 You want to provide a lot of optional features for a class.
2 You want to use oRequestHandlerClassne particular feature in a lot of different classes.
在这些类的设计中始终围绕如何处理socket请求。通常,处理方式三种:
synchronous (one request is handled at a time)
forking (each request is handled by a new process)
threading (each request is handled by a new thread)
其中,BaseServer作为基础类,实现服务器的监听以及同步处理方法。初始化参数有两个:server_address和RequestHandlerClassserver_forever方法中使用select方式轮询,是否有客户端连接到服务器。
def serve_forever(self, poll_interval=0.5): self.__is_shut_down.clear() try: while not self.__shutdown_request: r, w, e = _eintr_retry(select.select, [self], [], [],poll_interval) if self in r: self._handle_request_noblock() finally: self.__shutdown_request = False self.__is_shut_down.set()
如果有客户端连接,则使用同步的方式进行处理,最终调用一个RequestHandlerClass类进行处理。
def _handle_request_noblock(self): try: request, client_address = self.get_request() except socket.error: return if self.verify_request(request, client_address): try: self.process_request(request, client_address) except: self.handle_error(request, client_address) self.shutdown_request(request) def process_request(self, request, client_address): self.finish_request(request, client_address) self.shutdown_request(request) def finish_request(self, request, client_address): self.RequestHandlerClass(request, client_address, self)
其中,TCPServer继承自BaseServer,加入了TCP的一些配置,但是运行机制时完全继承的。所以,此时的TCPServer就是第一种情情况。而多进程和多线程方式则通过mixin设计而成。以多线程的ThreadingTCPServer为例:
class ThreadingMixIn: daemon_threads = False def process_request_thread(self, request, client_address): try: self.finish_request(request, client_address) self.shutdown_request(request) except: self.handle_error(request, client_address) self.shutdown_request(request) def process_request(self, request, client_address): t = threading.Thread(target = self.process_request_thread, args = (request, client_address)) t.daemon = self.daemon_threads t.start()
在ThreadingMixIn类中,覆写process_request方法,对于每个request都创建一个线程进行处理。此时,多线程的情况只要这样:
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
注意,mixin类要放在前面,因为它覆写了TCPServer类的process_request方法。
在SocketServer完美体现了mixin两个设计原则:
ThreadingMixIn这个mixin类作为一个多线程的特性附加在了TCPServer上,同时这个特性又不仅仅是提供给TCPServer使用,还给UDPServer使用。
- 相关文章推荐:
- python 日志打印功能学习
- python sys模块的一些常用功能
- python beautifulsoup多线程分析并抓取网页
- 本文来自:爱好Linux技术网
- 本文链接:http://www.ahlinux.com/python/9109.html