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 方法。 至此代码分析完成!!!! '''

浙公网安备 33010602011771号