zoukankan      html  css  js  c++  java
  • socketserver模块使用方法

    一、socketserver模块介绍

    Python提供了两个基本的socket模块。一个是socket,它提供了标准的BSD Socket API; 另一个是socketserver,它提供了服务器中心类,可以简化网络服务器的开发

    socketserver

    socketserver内部使用IO多路复用以及“多线程”和“多进程”,从而实现并发处理多个客户端请求的socket服务端。 即,每个客服端请求连接到服务器时,socket服务端都会在服务器上创建一个“线程”或“进程”专门负责处理当前客户端的所有请求。

    二、socketserver中的ThreadingTCPServer类

    ThreadingTCPServer实现的socket服务器内部会为每个client创建一个“线程”,该线程用来和客户端就行交互 ThreadingTCPServer源码内容:

    class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass
    
    
    #可以看到ThreadTCPServer类本身并没有方法,而是继承了(ThreadingMinIn, TCPServer) 这两个类。 而TCPServer则是继承了BaseServer类。

    三、ThreadingTCPServer的使用方法

    1、创建一个继承socketserver.BaseRequestHandler的类

    2、类中必须重写一个名为handler的方法

    3、实例化一个服务器类,传入服务器的地址和请求处理程序类

    4、调用serve_forever()事件循环监听

    #!/usr/bin/env python3
    import socketserver
    
    class Handler(socketserver.BaseRequestHandler):    # 必须继承BaseRequestHandler
        def handle(self):        # 必须有handle方法
            print('New connection:',self.client_address)
            while True:
                data = self.request.recv(1024)
                if not data:break
                print('Client data:',data.decode())
                self.request.send(data)
    
    if __name__ == '__main__':
        server = socketserver.ThreadingTCPServer(('127.0.0.1',8009),Handler)    # 实例化对象,实现多线程的socket
        server.serve_forever()    # 事件监听,并调用handler方法
    View Code

    四、ThreadingTCPServer执行过程

    1、启动服务端程序

    2、执行TCPServer.__init__方法,创建服务端socket对象并绑定IP和端口(根据类的继承关系,即查找顺序找到TCPServer.__init__())

    3、执行BaseServer.__init__方法,将自定义的继承自socketserver.BaseRequestHandler的类MyRequestHandler赋值给self.RequestHandlerClass class TCPServer(BaseServer): #(继承了BaseServeer类)

    class TCPServer(BaseServer): #(继承了BaseServeer类)
        def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
            """Constructor.  May be extended, do not override."""
            BaseServer.__init__(self, server_address, RequestHandlerClass)  #(重写了BaseServer的__init__方法)
            self.socket = socket.socket(self.address_family,
                                        self.socket_type)
            if bind_and_activate:
                try:
                    self.server_bind()
                    self.server_activate()
                except:
                    self.server_close()
                    raise
    
    class BaseServer:
        def __init__(self, server_address, RequestHandlerClass):  #(接收了两个传进来的参数)
            """Constructor.  May be extended, do not override."""
            self.server_address = server_address
            self.RequestHandlerClass = RequestHandlerClass     #(赋值给了self.RequestHandlerClass)
            self.__is_shut_down = threading.Event()
            self.__shutdown_request = False
    View Code

    4、通过实例化的对象,执行serve_forever方法,该方法首先查找到BaseServer下的方法,通过调用selector模块,注册事件监听对象,并执行_handle_request_noblock方法 找到此方法,并调用该方法下的process_request方法,在此调用到finish_request方法,通过finish_request方法,执行了RequestHandlerClass方法,执行此方法就相当于调用 了我们重写的Handler类。

    class BaseServer:
        def serve_forever(self, poll_interval=0.5):
            try:
                with _ServerSelector() as selector:
                    selector.register(self, selectors.EVENT_READ)
    
                    while not self.__shutdown_request:
                        ready = selector.select(poll_interval)
                        if ready:
                            self._handle_request_noblock()
    
                        self.service_actions()
       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)
        def process_request(self, request, client_address):
            self.finish_request(request, client_address)
            self.shutdown_request(request)
        def finish_request(self, request, client_address):
            self.RequestHandlerClass(request, client_address, self)
    View Code

    5、通过Handler类实例化对象,调用继承的BaseRequestHandler类中的__init__方法,并执行了handler方法。 从而运行了我们重写Handler类中的handler方法。

    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()   #调用handler()
            finally:
                self.finish()
    View Code

    五、调用流程图

  • 相关阅读:
    Leetcode字符串算法
    Leetcode基础算法结构-目录结构
    python日志-loguru日志管理
    FastApi
    python-hashlib
    excel数据操作
    yagmail自动发邮件
    python-sys
    集合
    文件操作
  • 原文地址:https://www.cnblogs.com/jeavy/p/9502555.html
Copyright © 2011-2022 走看看