python 内置标准库socketserver模块的思考

时间:2021-11-21 23:58:19

socketserver模块简化了编写网络服务器的任务, 在很大程度上封装了一些操作, 你可以看成是事件驱动型的设计, 这很不错。它定义了两个最基本的类--服务器类 BaseServer, 请求处理类 BaseRequestHandler.

BaseServer 基本服务器类封装了基本的一些socket操作, socket原语中对socket的相关操作仅仅封装到了accept 方法, 此方法之前的操作也封装完了, 接下来的send, recv原语操作就没有在进行封装了, 那么它哪去了呢?这是socketserver模块设计的很好的地方, socketserver不仅仅有对socket原语操作的, 还有对需要进行具体处理的基类封装, 那就是BaseRequestHandler 类.举两个例子, 首先是WSGI协议的处理, 具体请看<深入浅出web服务器与python应用程序之间的联系 http://www.cnblogs.com/zhiyong-ITNote/p/7522093.html>. 找到python 的安装目录里面的wsgiref 文件夹, 我们分析下simple_server.py模块, 以及handlers.py模块。
注意下 simple_server.py模块的make_server 函数, 该函数的第五个参数就是自定义的请求处理类, 我们利用这个类来处理WSGI协议, 以实现服务器与python 应用程序之间的通信. 我们看看这个类的继承顺序:
WSGIRequestHandler → BaseHTTPRequestHandler → StreamRequestHandler → BaseRequestHandler.
我们看看最终父类的实现:

class 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 other arbitrary instance variables.

"""

def __init__(self, request, client_address, server):
self.request
= request
self.client_address
= client_address
self.server
= server
self.setup()
try:
self.handle()
finally:
self.finish()

def setup(self):
pass

def handle(self):
pass

def finish(self):
pass

我们注意下注释中对handle() 函数的解释, 此函数是对每个请求的实际处理. 我们回到WSGIRequestHandler的程序中, WSGIRequestHandler 类中有一个handle() 函数, 此函数就是重写并实现了基类的handle() 函数, 将请求处理分到了handlers.py这个模块中, 用来处理WSGI协议.

第二个例子就是python 自带的HTTPServer, 我们在python 3下启动自带的HTTPServer, 在命令行敲入:
python -m http.server 8000
看看浏览器的响应:
python 内置标准库socketserver模块的思考

打开python安装目录下的http文件夹, 我们看看server.py这个文件, 然后我们看看test() 这个测试函数的代码, 找到其中的HandlerClass变量, 其指向的是SimpleHTTPRequestHandler类, 我们看看这个类的继承顺序:
SimpleHTTPRequestHandler → BaseHTTPRequestHandler → StreamRequestHandler → BaseRequestHandler
上面的第三个类是用来处理TCP流式通信的, 可以看到HTTPServer 的请求处理最后还是基于BaseRequestHandler类, 而且具体的还是使用handle() 函数来处理, BaseHTTPRequestHandler类中的handle() 函数分发了处理请求的任务给其他函数.

最后做下总结吧, python两个内置的实现都是基于socketserver.py模块, 主要就是调用了BaseServer类与BaseRequestHandler类, 前者封装了基本的socket处理, 后者封装了对请求的处理, 通过其内的handle()函数将请求处理分发给了其他的具体处理.