• socketserver模块


      socketserver中包含了两种类,一种为服务类(server class),一种为请求处理类(request handle class)。前者提供了许多方法:像绑定,监听,运行…… (也就是建立连接的过程) 后者则专注于如何处理用户所发送的数据(也就是事务逻辑)。

      一般情况下,所有的服务,都是先建立连接,也就是建立一个服务类的实例,然后开始处理用户请求,也就是建立一个请求处理类的实例。

      我们分析一下源码,来看一看服务类是如何与请求处理类建立联系的。

    class BaseServer:#我们创建服务类时,需要指定(地址,端口),服务处理类。
        def __init__(self, server_address, RequestHandlerClass):
            """Constructor.  May be extended, do not override."""
            self.server_address = server_address
            self.RequestHandlerClass = RequestHandlerClass
            self.__is_shut_down = threading.Event()
            self.__shutdown_request = False
         #…………此处省略n多代码,当我们执行server_forever方法时,里面就会调用很多服务类中的其他方法,但最终会调用finish_request方法。
    
        def finish_request(self, request, client_address):
            """Finish one request by instantiating RequestHandlerClass."""
            self.RequestHandlerClass(request, client_address, self)
         #finish_request方法中执行了self.RequestHandlerClass(request, client_address, self)。self.RequestHandlerClass是什么呢?#self.RequestHandlerClass = RequestHandlerClass(就在__init__方法中)。所以finish_request方法本质上就是创建了一个服务处理实例。
    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()
            finally:
                self.finish()#当我们创建服务处理类实例时,就会运行handle()方法,而handle()方法则一般是我们处理事务逻辑的代码块。
         #…………此处省略n多代码
    

    先来看服务类:

    5种类型:BaseServer,TCPServer,UnixStreamServer,UDPServer,UnixDatagramServer。

    BaseServer不直接对外服务。

    TCPServer针对TCP套接字流

    UDPServer针对UDP数据报套接字

    UnixStreamServer和UnixDatagramServer针对UNIX域套接字,不常用。

    他们之间的继承关系:

     

    请求处理器类:

     要实现一项服务,还必须派生一个handler class请求处理类,并重写父类的handle()方法。handle方法就是用来专门是处理请求的。该模块是通过服务类和请求处理类组合来处理请求的。

     SocketServer模块提供的请求处理类有BaseRequestHandler,以及它的派生类StreamRequestHandler和DatagramRequestHandler。从名字看出可以一个处理流式套接字,一个处理数据报套接字。

    请求处理类有三种方法:

    setup()
        Called before the handle() method to perform any initialization actions required. The default implementation does nothing.
        也就是在handle()之前被调用,主要的作用就是执行处理请求之前的初始化相关的各种工作。默认不会做任何事。(如果想要让其做一些事的话,就要程序员在自己的请求处理器中覆盖这个方法(因为一般自定义的请求处理器都要继承python中提供的BaseRequestHandler,ps:下文会提到的),然后往里面添加东西即可)
    
    handle()
        This function must do all the work required to service a request. The default implementation does nothing. Several instance attributes are available to it; the request is available as self.request; the client address as self.client_address; and the server instance as self.server, in case it needs access to per-server information.
        The type of self.request is different for datagram or stream services. For stream services,self.request is a socket object; for datagram services, self.request is a pair of string and socket.
        handle()的工作就是做那些所有与处理请求相关的工作。默认也不会做任何事。他有数个实例参数:self.request    self.client_address   self.server
    
    finish()
        Called after the handle() method to perform any clean-up actions required. The default implementation does nothing. If setup() raises an exception, this function will not be called.
        在handle()方法之后会被调用,他的作用就是执行当处理完请求后的清理工作,默认不会做任何事
    

     服务端

    import socketserver
    
    class MyTCPHandler(socketserver.BaseRequestHandler):
        def handle(self):
            try:
                while True:
                    self.data=self.request.recv(1024)
                    print("{} send:".format(self.client_address),self.data)
                    if not self.data:
                        print("connection lost")
                        break
                    self.request.sendall(self.data.upper())
            except Exception as e:
                print(self.client_address,"连接断开")
            finally:
                self.request.close()
        def setup(self):
            print("before handle,连接建立:",self.client_address)
        def finish(self):
            print("finish run  after handle")
    
    if __name__=="__main__":
        HOST,PORT = "localhost",9988
        server=socketserver.TCPServer((HOST,PORT),MyTCPHandler)
    
        server.serve_forever()
    

     客户端

    import socket
    
    client=socket.socket()
    
    client.connect(('localhost',9988))
    while True:
        cmd=input("(quit退出)>>").strip()
        if len(cmd)==0:
            continue
        if cmd=="quit":
            break
        client.send(cmd.encode())
        cmd_res=client.recv(1024)
        print(cmd_res.decode())
    
    client.close()
    

     异步处理

    import socketserver
    
    class MyTCPHandler(socketserver.BaseRequestHandler):
        def handle(self):
            try:
                while True:
                    self.data=self.request.recv(1024)
                    print("{} send:".format(self.client_address),self.data)
                    if not self.data:
                        print("connection lost")
                        break
                    self.request.sendall(self.data.upper())
            except Exception as e:
                print(self.client_address,"连接断开")
            finally:
                self.request.close()
        def setup(self):
            print("before handle,连接建立:",self.client_address)
        def finish(self):
            print("finish run  after handle")
    
    
    HOST,PORT = "localhost",9999
    
    server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)#多线程版
    server.serve_forever()
    
  • 相关阅读:
    EC++学习笔记(五) 实现
    EC++学习笔记(三) 资源管理
    EC++学习笔记(一) 习惯c++
    EC++学习笔记(六) 继承和面向对象设计
    STL学习笔记(三) 关联容器
    STL学习笔记(一) 容器
    背包问题详解
    EC++学习笔记(二) 构造/析构/赋值
    STL学习笔记(四) 迭代器
    常用安全测试用例
  • 原文地址:https://www.cnblogs.com/wuyuan2011woaini/p/15974698.html
Copyright © 2020-2023  润新知