SocketServer
概述
- socket编程过于底层,编程虽然有套路,但是想要写出健壮的代码还是比较困难的,所以很多语言都对socket底层API进行封装
- Python的封装就是——socketserver模块。它是网络服务编程框架,便于企业级快速开发
类的继承关系
+------------+
| BaseServer |
+------------+
|
v
+-----------+ +------------------+
| TCPServer |------->| UnixStreamServer |
+-----------+ +------------------+
|
v
+-----------+ +--------------------+
| UDPServer |------->| UnixDatagramServer |
+-----------+ +--------------------+
SocketServer简化了网络服务器的编写
它有4个同步类:
- TCPServer
- UDPServer
- UnixStreamServer
- UnixDatagramServer
2个Mixin类:ForkingMixIn 和 ThreadingMixIn 类,用来支持异步。由此得到
- class ForkingUDPServer(ForkingMixIn, UDPServer): pass
- class ForkingTCPServer(ForkingMixIn, TCPServer): pass
- class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass
- class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
fork是创建多进程,thread是创建多线程
fork需要操作系统支持,Windows不支持
编程接口
socketserver.BaseServer(server_address, RequestHandlerClass)
需要提供服务器绑定的地址信息,和用于处理请求的RequestHandlerClass类
RequestHandlerClass类必须是BaseRequestHandler类的子类,在BaseServer中代码如下:
# BaseServer代码
class BaseServer:
def __init__(self, server_address, RequestHandlerClass):
"""Constructor. May be extended, do not override."""
self.server_address = server_address
self.RequestHandlerClass = RequestHandlerClass
self.__is_shut_down = threading.Event()
self.__shutdown_request = False
def finish_request(self, request, client_address): # 处理请求的方法
"""Finish one request by instantiating RequestHandlerClass."""
self.RequestHandlerClass(request, client_address, self) # RequestHandlerClass构造
BaseRequestHandler类
它是和用户连接的用户请求处理类的基类,定义为
BaseRequestHandler(request, client_address, server)
服务端Server实例接收用户请求后,最后会实例化这个类
它被初始化时,送入3个构造参数:request
, client_address
, server自身
以后就可以在BaseRequestHandler类的实例上使用以下属性:
self.request
是和客户端的连接的socket对象self.server
是TCPServer实例本身self.client_address
是客户端地址
这个类在初始化的时候,它会依次调用3个方法。子类可以覆盖这些方法
# BaseRequestHandler要子类覆盖的方法
class BaseRequestHandler:
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
测试代码
import threading
import socketserver
class Myhandler(socketserver.BaseRequestHandler):
def handle(self):
# super().handle() # 可以不调用,父类handle什么都没有做
print('-' * 30)
print(self.server) # 服务
print(self.request) # 服务端负责客户端连接请求的socket对象
print(self.client_address) # 客户端地址
print