导语:大牛们常常说阅读源码是很低效的学习方法。但对我辈初学者而言,阅读源码却是掌握编程思想、编码规范的好途径。简而言之,读源码不是万能的,不读源码是万万不能的。
SocketServer是标准库中一个很具有代表性的库。它基于socket提供一套快速建立socket服务器的框架,并可以通过Mix-in的技巧让单线程服务器进化为多线程或多进程服务器。Socketserver.py里面的类很多,下面一个一个介绍并介绍它们之间关系。
BaseServer、TCPServer、UDPServer,前者是后两者的父类。在父类中实现了TCP与UDP服务器可以共用的方法,并留下了需要在子类中实现的抽象类。因此在实际工作中,我们一般不应该继承BaseServer类,除非你是为了自己去实现或重载某些方法。另外,还有UnixStreamServer和UnixDatagramServer分别继承自TCPserver和UDPServer。这两个带Unix字样的类是用来构建*nix下本地socket的服务器(本地socket访问速度更快,但只能用在本机的进程间通信)
接下来是ForkingMixIn和ThreadingMixIn两个混合类,它们都提供Server类中process_request方法的新实现,前者在处理每次用户连接的时候都会开启新的进程,而后者会开启新的线程。想要让Server类实现并发处理,只用利用多重继承即可。或者直接使用已经混合好的
class ForkingUDPServer(ForkingMixIn, UDPServer): pass
class ForkingTCPServer(ForkingMixIn, TCPServer): pass
class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
最后没有介绍的是BaseRequestHandler、StreamRequestHandler、DatagramRequestHandler,同Server一样,前者是后两者的父类用来提供公用的方法
通常在使用SocketServer的时候我们只用自己实例化一个合适的Server类,并在实例化时传递其监听的IP、端口,以及之前继承自某个RequestHandler的类(需要自行实现hanle方法,作为server的请求处理器)
这里需要特别注意的:
1.IP和端口是作为一个元组传递的而不是两个单独的参数。
2.每个客户连接都会在hanle方法运行完之后被关闭,你如果不想关闭就需要重写Server中的def shutdown_request(self, request)方法
___________________我是华丽丽的分割线________________________
可以说这个标准库用起来还很方便的,但功能上还是有一些不足。
1.它没有提供各个hanle实例之间的通信机制,因此客户端互发消息还是需要自己实现一个观察者模型。
不过这个功能似乎也超过了SocketServer的工作职责了。我们可以自己实现,也可以使用python-message这个国产第三方库来进行线程间基于消息的编程。
2.它提供了多线程多进程的解决方案,但没有异步方案的server每次访问都是阻塞的
关于这点我感觉很遗憾,不过这个库也不是太复杂,大不了自己写一个异步的socketserver吧,自己动手丰衣足食!
因为本来就是是对源码的解读,所以这篇文章没有放什么代码。读者完全可以自己去标准库里翻翻看,注释写的真的很赞。