python基础socketserver 模块源码分析过程

 

 

基本格式:

import socketserver

class MyServer(socketserver.BaseRequestHandler):
    
    '''
    重写 父类的 handle 方法,实现业务核心逻辑
    '''
    def handle(self):
        pass



if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('192.168.0.105.',8009),MyServer)
    server.serve_forever()

代码示例:

class MyServer(socketserver.BaseRequestHandler):

    def handle(self):
        while True:
            data = self.request.recv(1024).decode()
            if data == 'exit':
                print('连接断开')
                break
            print('接收到客户端{}的消息{}'.format(self.client_address,data))
            res = data.upper()   # 小写字母转大写
            self.request.send(res.encode())
        self.request.close()



if __name__ == '__main__':
    server = socketserver.ThreadingTCPServer(('192.168.0.105.',8009),MyServer)
    server.serve_forever()

 socketserver模块 源码分析:

源码分析:


'''
解析过程:
1、创建一个ThreadingTCPServer 传入的是 一个 ip,端口,+自定义的类 ,类+实例 =》走 类的init方法 
2、查找init 方法:先从当前类中寻找 ThreadingTCPServer ,
当前类没有init 方法 class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass ,
从其继承的父类中查找  ThreadingMixIn 没有init 方法 ,
TCPServer 中有init 方法  ,故会执行TCPServer 类中的init 方法:

class TCPserver(BaseServer):
    def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
    """Constructor.  May be extended, do not override."""
        # 先执行BaseServer 中的init 方法 ,
        BaseServer.__init__(self, server_address, RequestHandlerClass)   #相当于做了个实例变量的赋值
        RequestHandlerClass 即自定义的MyServer 这个类 
        执行完毕 创建 socket 套接字对象 
        self.socket = socket.socket(self.address_family,
                                    self.socket_type)
        if bind_and_activate:
            try:
                self.server_bind()      # 创建完对象后,绑定ip和端口
                self.server_activate()  #设置监听传入连接 的数量
            except:
                self.server_close()     # 如果 绑定 和设置数量失败,则关闭当前服务端的套接字对象
                raise
至此 执行完对应类的init 方法后,总共做了以下几件事情1)、创建了socket 套接字对象,2)、给这个套接字对象bind ip和端口 3)、设置监听传入连接的数量

3、猜想:创建一个完整的服务端 还需要 接收客户端连接的这个步骤  ,猜想该步骤应该在 serve_forever() 中实现   

注意 不要通过 ctrl +左键的方式去查找对应的方法
要根据类的继承关系去查找!!!!! 
ThreadingMixIn 中无  serve_forever 
TCPServer  中无 serve_forever    但是 TCPServer 继承 BaseServer ,故要从BaseServer 中查找
 经在TCPServer 父类中BaseServer 查找到 serve_forever 方法
    def serve_forever(self, poll_interval=0.5):
        self.__is_shut_down.clear()
        try:
           
            with _ServerSelector() as selector:
                selector.register(self, selectors.EVENT_READ)

                while not self.__shutdown_request:
                    ready = selector.select(poll_interval)
                    # bpo-35017: shutdown() called during select(), exit immediately.
                    if self.__shutdown_request:
                        break
                        
                    if ready:
                        self._handle_request_noblock()

                    self.service_actions()
        finally:
            self.__shutdown_request = False
            self.__is_shut_down.set()

 查看 BaseServe 类中的serve_forever 方法   self._handle_request_noblock() 
  查找_handle_request_noblock 方法,经查 该方法在 BaseServe 中:
   def _handle_request_noblock(self):
        try:
            request, client_address = self.get_request()
        except OSError:
            return
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)
            except Exception:
                self.handle_error(request, client_address)
                self.shutdown_request(request)
            except:
                self.shutdown_request(request)
                raise
        else:
            self.shutdown_request(request)    
分析:  request, client_address = self.get_request() 此行代码 和accept()类似  conn,address = socket.accept()
 查找其 get_request ,继续从头开始找(当前对象的类继承顺序查找)
 经查,在TCPserver类中查找到该方法 :
    def get_request(self):
        return self.socket.accept()
 查看此处直接调用的socket的accept 方法,验证了上面的猜想,
 返回到_handle_request_noblock 继续往下看
        try:
            request, client_address = self.get_request()
        except OSError:
            return
        if self.verify_request(request, client_address):
            try:
                self.process_request(request, client_address)
                
                
核心:查找实现多线程相关逻辑代码
代码分析至此处已完成,1、socket 创建,2、bind  ,3、listen, 4、accept ,
当前的需求是实现单个 server 同时接入多个client 处理 
故还差 多线程或者多进程代码
查看上述代码  self.process_request(request, client_address)  ,
查找:process_request 
在 ThreadingMixIn 查找到 该方法
    def process_request(self, request, client_address):
        
        t = threading.Thread(target = self.process_request_thread,
                             args = (request, client_address))   #此处调用通过创建一个线程调用 process_request_thread方法执行  
        t.daemon = self.daemon_threads
        
        if not t.daemon and self.block_on_close:
            if self._threads is None:
                self._threads = []
            self._threads.append(t)
        t.start()
查看发现 有创建线程去调用  process_request_thread方法 

核心:发现线程 执行的是process_request_thread 方法
继续查找 process_request_thread方法:
    def process_request_thread(self, request, client_address):
        try:
            self.finish_request(request, client_address)
        except Exception:
            self.handle_error(request, client_address)
        finally:
            self.shutdown_request(request)
通常异常捕获 ,核心代码是try里面的 ,在try中 看到finish_request 方法,
继续查找 finish_request 方法:
最终在 BaseServer 类中 查找到 finish_request
    def finish_request(self, request, client_address):
        self.RequestHandlerClass(request, client_address, self)
该方方法传入request 和 client_address  ,然后将参数传给 RequestHandlerClass 这个类 等价于,这个类去执行init 方法 
request:  历史分析中的代码中 request, client_address = self.get_request()  判断 request 就是 客户端的套接字对象 也就是conn,
client_address 就是ip和端口号



核心:发现线程执行的是 handle 方法,查找 handle()方法在哪里执行
(备注:RequestHandlerClass 就是 自定义的class MyServer(socketserver.BaseRequestHandler):) 自定义类中没有init 方法
故从父类中查找 init 方法
    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.server = server
        self.setup()
        try:
            self.handle()   #父类中init 方法 执行了 handle
        finally:
            self.finish()

最终在 自定义类中的父类 init 方法中 执行handle 方法,而handle 方法 在 自定义类中 进行了重写,故这里子类调用的时候 执行的是当前对象类中重写的
handle 方法。

至此代码分析完成!!!!


'''

 

 

posted @ 2021-11-15 00:21  昆虫白  阅读(223)  评论(0)    收藏  举报