1、SocketServer:

  socket编程过于底层,编程虽然有套路,但是想要写出健壮的代码还是比较困难的,所以很多语言都对socket底层
  API进行封装,Python的封装就是——socketserver模块。它是网络服务编程框架,便于企业级快速开发

2、类的继承关系:

+------------+
| 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是创建多线程

3、编程接口:

  socketserver.BaseServer(server_address, RequestHandlerClass)
  需要提供服务器绑定的地址信息,和用于处理请求的RequestHandlerClass类。
  RequestHandlerClass类必须是BaseRequestHandler类的子类,在BaseServer中代码如下:

 1 # BaseServer代码 ----》
 2 class BaseServer:
 3   def __init__(self, server_address, RequestHandlerClass):
 4     """Constructor. May be extended, do not override."""
 5     self.server_address = server_address
 6     self.RequestHandlerClass = RequestHandlerClass
 7     self.__is_shut_down = threading.Event()
 8     self.__shutdown_request = False
 9   def finish_request(self, request, client_address): # 处理请求的方法
10     """Finish one request by instantiating RequestHandlerClass."""
11     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个方法。子类可以覆盖这些方法。

 1 # BaseRequestHandler要子类覆盖的方法
 2 class BaseRequestHandler:
 3   def __init__(self, request, client_address, server):
 4     self.request = request
 5     self.client_address = client_address
 6     self.server = server
 7     self.setup()
 8   try:
 9     self.handle()
10   finally:
11     self.finish()
12   def setup(self): # 每一个连接初始化
13     pass
14   def handle(self): # 每一次请求处理
15     pass
16   def finish(self): # 每一个连接清理
17     pass

 

  测试:

 1 import threading
 2 import socketserver
 3 
 4 class MyHandler(socketserver.BaseRequestHandler):
 5     def handle(self):
 6         # super().handle() # 可以不调用,父类handle什么都没有做,一般习惯性的调用一下父类的
 7         print('-'*30)
 8         print(self.__dict__)
 9         print(self.server) # 服务
10         print(self.request) # 服务端负责客户端连接请求的socket对象
11         print(self.client_address) # 客户端地址
12         print(self.__dict__)
13         print(self.server.__dict__) # 能看到负责accept的socket
14 
15         print(threading.enumerate())
16         print(threading.current_thread())
17         print('-'*30)
18 
19 addr = ('127.0.0.1', 9999)
20 server = socketserver.ThreadingTCPServer(addr, MyHandler) # 生成一个多线程的server
21 print(server.__class__.__name__)
22 
23 
24 server.serve_forever() # 永久开启
测试

相关文章: