• socketserver源码简介


    一、socketserver流程简介

            +------------+
            | BaseServer |
            +------------+
                  |
                  v
            +-----------+        +------------------+
            | TCPServer |------->| UnixStreamServer |
            +-----------+        +------------------+
                  |
                  v
            +-----------+        +--------------------+
            | UDPServer |------->| UnixDatagramServer |
            +-----------+        +--------------------+
    # 继承关系如下
    
    class TCPServer(BaseServer):
    class UDPServer(TCPServer):
    class UnixStreamServer(TCPServer):
            address_family = socket.AF_UNIX
    
    class UnixDatagramServer(UDPServer):
           address_family = socket.AF_UNIX

    先来看一下并发聊天的简单例子:

    #################### server.py 端
    # author:wanstack
    
    import socketserver
    
    class MyServer(socketserver.BaseRequestHandler):
    
        def handle(self):
            print ("服务端启动...")
            while True:
                # conn = sk.accept() 获取到客户端的socket对象
                conn = self.request
                print (self.client_address)
                while True:
                    client_data=conn.recv(1024)
                    print (str(client_data,"utf8"))
                    print ("waiting...")
                    conn.sendall(client_data)
                conn.close()
    
    if __name__ == '__main__':
        server = socketserver.ThreadingTCPServer(('127.0.0.1',8091),MyServer)
        server.serve_forever()
    
    
    
    ############# client 端
    # author:wanstack
    
    import socket
    
    ip_port = ('127.0.0.1',8091)
    sk = socket.socket()
    sk.connect(ip_port)
    print ("客户端启动:")
    while True:
        inp = input('>>>')
        sk.sendall(bytes(inp,"utf8"))
        if inp == 'exit':
            break
        server_response=sk.recv(1024)
        print (str(server_response,"utf8"))
    sk.close()

    根据上面的例子,我们可以依次看一下socketserver的执行流程,为什么是handle方法来处理咱们的流程。

    1、程序先执行

    server = socketserver.ThreadingTCPServer(('127.0.0.1',8091),MyServer)

    这里看起来像是对一个socketserver 模块下的 ThreadingTCPServer 类进行实例化的过程。接收2个参数第一个参数是一个元组('127.0.0.1',8091)

    ,第二个参数是我们自定义的类名MyServer

    class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass

    程序调转到这里,继承(ThreadingMixIn, TCPServer) 2个父类,这个 ThreadingTCPServer 类啥都没干。去父类中找构造函数,先去ThreadingMixIn类中找,如果找不到去TCPServer的类找构造函数。ThreadingMixIn类中没有构造函数,所以构造方法在TCPServer中。

    class TCPServer(BaseServer):
    
        """Base class for various socket-based server classes.
    
        Defaults to synchronous IP stream (i.e., TCP).
    
        Methods for the caller:
    
        - __init__(server_address, RequestHandlerClass, bind_and_activate=True)
        - serve_forever(poll_interval=0.5)
        - shutdown()
        - handle_request()  # if you don't use serve_forever()
        - fileno() -> int   # for selector
    
        Methods that may be overridden:
    
        - server_bind()
        - server_activate()
        - get_request() -> request, client_address
        - handle_timeout()
        - verify_request(request, client_address)
        - process_request(request, client_address)
        - shutdown_request(request)
        - close_request(request)
        - handle_error()
    
        Methods for derived classes:
    
        - finish_request(request, client_address)
    
        Class variables that may be overridden by derived classes or
        instances:
    
        - timeout
        - address_family
        - socket_type
        - request_queue_size (only for stream sockets)
        - allow_reuse_address
    
        Instance variables:
    
        - server_address
        - RequestHandlerClass
        - socket
    
        """
    
        address_family = socket.AF_INET
    
        socket_type = socket.SOCK_STREAM
    
        request_queue_size = 5
    
        allow_reuse_address = False
    
        def __init__(self, server_address, RequestHandlerClass, bind_and_activate=True):
            """Constructor.  May be extended, do not override."""
            # 这里是执行的BaseServer的构造方法,只是执行了一些赋值操作
            BaseServer.__init__(self, server_address, RequestHandlerClass)
            # 创建socket的对象,是基于IPV4和TCP协议的
            self.socket = socket.socket(self.address_family,
                                        self.socket_type)
            if bind_and_activate:
                try:
                    # 下面的bind()方法,bind我们传入的ip和port
                    self.server_bind()
                    # 这里是listen(),默认为5个
                    self.server_activate()
                except:
                    self.server_close()
                    raise
    
        def server_bind(self):
            """Called by constructor to bind the socket.
    
            May be overridden.
    
            """
            if self.allow_reuse_address:
                self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.socket.bind(self.server_address)
            self.server_address = self.socket.getsockname()
    
        def server_activate(self):
            """Called by constructor to activate the server.
    
            May be overridden.
    
            """
            self.socket.listen(self.request_queue_size)
    
        def server_close(self):
            """Called to clean-up the server.
    
            May be overridden.
    
            """
            self.socket.close()

    程序到这里我们就执行完了构造方法。下面开始执行

    server.serve_forever()

    请务必记住这里的server是  socketserver.ThreadingTCPServer(('127.0.0.1',8091),MyServer) 实例化的对象。

    根据查询流程

    ThreadingTCPServer ---> ThreadingMixIn ---> TCPServer ---> BaseServer 最终在BaseServer类中找到了


    生活不会突变,你要做的只是耐心和积累。人这一辈子没法做太多的事情,所以每一件都要做得精彩绝伦。你的时间有限,做喜欢的事情会令人愉悦,所以跟随自己的本心。
  • 相关阅读:
    complete完成量——实例分析
    worker线程的创建与使用
    SDIO接口
    Linux中V4L2分析
    Linux系统调用分析
    ppm图片显示
    应用层与内核层错误打印函数总结
    高通Sensor驱动学习笔记
    linux中新增一个shell命令的方法
    RTC测试程序
  • 原文地址:https://www.cnblogs.com/wanstack/p/7126293.html
Copyright © 2020-2023  润新知