• chapter12.3、SocketServer


    SocketServer

    socket编程过于底层,编程虽然有套路,但是想要写出健壮的代码还是比较困难的,所以很多语言都对socket底层API进行封装,Python的封装就是——socketserver模块。它是网络服务编程框架,便于企业级快速开发。

    SocketServer简化了网络服务器的编写。

    它有4个同步类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramServer。

    2个Mixin类:ForkingMixIn 和 ThreadingMixIn 类,用来支持异步。

    class ForkingUDPServer(ForkingMixIn, UDPServer): pass

    class ForkingTCPServer(ForkingMixIn, TCPServer): pass

    class ThreadingUDPServer(ThreadingMixIn, UDPServer): pass

    class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass

    fork是创建多进程,thread是创建多线程

    编程接口

    socketserver.BaseServer(server_address, RequestHandlerClass)

    需要提供服务器绑定的地址信息,和用于处理请求的RequestHandlerClass类。

    RequestHandlerClass类必须是BaseRequestHandler类的子类。

    BaseRequestHandler类

    它是和用户连接的用户请求处理类的基类,定义为BaseRequestHandler(request, client_address, server)

    服务端Server实例接收用户请求后,最后会实例化这个类。

    它被初始化时,送入3个构造参数:request, client_address, server自身

    以后就可以在BaseRequestHandler类的实例上使用以下属性:

    self.request是和客户端的连接的socket对象

    self.server是TCPServer实例本身

    self.client_address是客户端地址

    这个类在初始化的时候,它会依次调用3个方法。子类可以覆盖这些方法。

    # BaseRequestHandler要子类覆盖的方法
    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()
      def setup(self): # 每一个连接初始化
        pass
      def handle(self): # 每一次请求处理
        pass
      def finish(self): # 每一个连接清理
        pass

    ThreadingTCPServer是异步的,可以同时处理多个连接。

    TCPServer是同步的,一个连接处理完了,即一个连接的handle方法执行完了,才能处理另一个连接,且只有主线程。

    ThreadingTCPServer实现的群聊服务器

    Chat 
    import socketserver
    import threading
    import logging
    import sys
    
    FORMAT = "%(asctime)s %(thread)s %(message)s"
    logging.basicConfig(format=FORMAT, level=logging.INFO)
    
    
    class ChatHandle(socketserver.BaseRequestHandler):
        clients = {}  # 记录客户端
    
        def setup(self):
            super().setup()
            self.even = threading.Event()
            self.clients[self.client_address] = self.request  # 添加客户端
    
        def finish(self):
            super().finish()
            self.even.set()
            self.clients.pop(self.client_address)  # 删除客户端
    
        def handle(self):
            super().handle()
            logging.info("{1}:{0}".format(self.request, self.client_address))
            while not self.even.is_set():
                try:
                    data = self.request.recv(1024)
                except Exception:
                    break
                if data.strip() == b"quit":
                    break
                msg = "{}{}".format(self.client_address, data.decode())
                logging.info(msg)
                msg = msg.encode()
                for f in self.clients.values():  # 发送给各个客户端
                    f.send(msg)
            print("end")
    
    
    def main():
        # 建立服务器
        server = socketserver.ThreadingTCPServer(("127.0.0.1", 9999), ChatHandle)
        threading.Thread(target=server.serve_forever, name="server").start()
        try:
            while True:
                cmd = input(">>>")
                if cmd.strip() == "quit":
                    server.shutdown()
                    break
                print(threading.enumerate())
        except Exception as e:
            print(e)
        except KeyboardInterrupt:
            pass
        finally:
            print("exit")
            sys.exit(0)
    
    
    if __name__ == '__main__':
        main()
    ThreadingTCPServer

    创建服务器需要几个步骤:

    1. 从BaseRequestHandler类派生出子类,并覆盖其handle()方法来创建请求处理程序类,此方法将处理传入请求

    2. 实例化一个服务器类,传参服务器的地址和请求处理类

    3. 调用服务器实例的handle_request()或serve_forever()方法

    4. 调用server_close()关闭套接字

     
     
     
     
     
     
  • 相关阅读:
    10个优秀HTML5网站案例赏析
    读书笔记之:More Exceptional C++ (2002) [++]
    函数模板与函数重载
    vector中元素的删除
    C++常用程序
    Linux下的示例程序
    要求或禁止在堆中产生对象
    读书笔记之:Effective C++ (2005)[++]
    读书笔记之:More Effective C++ (2007)[+]
    读书笔记之:Essential C++ (2001)[+]
  • 原文地址:https://www.cnblogs.com/rprp789/p/9905009.html
Copyright © 2020-2023  润新知