• socketserver


    socketserver模块简化了编写网络服务器的任务

    有4个基本的服务器类(server class):
    socketserver.TCPServer(server_address, RequestHandlerClass, bind_and_activate=True)

    socketserver.UDPServer(server_address, RequestHandlerClass, bind_and_activate=True)

    socketserver.UnixStreamServer(server_address, RequestHandlerClass, bind_and_activate=True)

    socketserver.UnixDatagramServer(server_address, RequestHandlerClass, bind_and_activate=True)

    这四个类是同步(Synchronous)进行处理的。要处理异步(Asynchronous),需使用ThreadingMixIn和ForkingMixIn类。

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

    1. you must create a request handler class by subclassing the BaseRequestHandler class and overriding its handle() method; this method will process incoming requests. 你必须创建一个请求处理类,这个类需继承BaseRequestHandler,并且重写父类的handle方法
    2. you must instantiate one of the server classes, passing it the server’s address and the request handler class. Then call the handle_request() or serve_forever() method of the server object to process one or many requests.  你必须实例化server classes(如TCPServer),并且传递server address和上面创建的请求处理类给server classes(如TCPServer),然后调用服务器对象(实例化的server classes)的handle_request()或serve_forever()方法来处理一个或多个请求。
    3. call server_close() to close the socket.调用server_close()关闭套接字。
    import socket
    
    HOST,PORT = "localhost",9999
    with socket.socket() as sock:
        sock.connect((HOST,PORT))
        sock.send("abc".encode())
    
        received = sock.recv(1024).decode()
    
        print("sent: {}".format("abc"))
        print("received:{}".format(received))
    socketserver_client
    import socketserver
    
    class MyTcpHandle(socketserver.BaseRequestHandler):  #第一步,创建一个请求处理类,并且重写handle
    
        def handle(self):   #客户端的请求都在handle来实现
            #self.request is the TCP socket conneted to le client
            self.data = self.request.recv(1024).strip()    #
            print("{} wrote:".format(self.client_address))
            print(self.data)
    
            self.request.send(self.data.upper())
    
    
    if __name__ == "__main__":
        HOST,PORT = "localhost",9999
    
        server = socketserver.TCPServer((HOST,PORT),MyTcpHandle)  #第二步,实例化服务器类
        server.serve_forever()
    socketserver_server

     上面仍不能与多个用户通信,此时我们需要用到异步,即ThreadingMixIn和ForkingMixIn,直接看代码

    import socket
    
    HOST,PORT = "localhost",9999
    with socket.socket() as sock:
    
       sock.connect((HOST,PORT))
       while True:
           data = input(">>").strip()
           if len(data) == 0:
               continue
           sock.send(data.encode())
    
           received = sock.recv(1024).decode()
    
           print("sent: {}".format(data))
           print("received:{}".format(received))
    socketserver_thread_client
    import socketserver
    import threading,socket
    
    
    class MyTcpHandle(socketserver.BaseRequestHandler):
    
        def handle(self):
            #self.request is the TCP socket conneted to le client
            while True:
                try:
                    self.data = self.request.recv(1024).strip()    #当客户端没有数据时会产生ConnectionResetError异常
                except ConnectionResetError as e:
                    print(e)
                    break
    
                print("{} wrote:".format(self.client_address))
                print(self.data)
                self.request.send(self.data.upper())
    
    
    class ThreadTCPServer(socketserver.ThreadingMixIn,socketserver.TCPServer):
        pass
    if __name__ == "__main__":
        HOST,PORT = "localhost",9999
    
        server = socketserver.ThreadingTCPServer((HOST,PORT),MyTcpHandle)  #继承ThreadingMixIn, TCPServer
        #实例化ThreadingTCPServer其实就是实例化TCPServer((HOST,PORT),MyTcpHandle)
        server.serve_forever()
        #最后其实是MyTcpHandle(finish_request中实现)实例化,self.request相当于在套接字中的conn(用户端实例), client_address(用户端地址和端口号)
    socketserver_thread_server

    根据源码分析可得,ThreadindTCPServer继承ThreadMixIn和TCPServer

    先看下第一步初始化

    server = socketserver.ThreadingTCPServer((HOST,PORT),MyTcpHandle)做了什么操作:

    1、通过继承关系知道ThreadingTCPServer初始化就是TCPServer初始化

    2、TCPServer初始化里面做了什么操作呢?先继承了BaseServer的构造方法然后初始化生成一个套接字socket,然后bind和listen

    3、BaseServer做了什么操作呢?对传进来的两个参数进行初始化分别赋值给:server_address和RequestHandlerClass,生成一个线程事件__is_shut_down=threading.Event来进行同步,对__shutdown_request 赋值False

    等学完select和多线程,要来分析下socketserver源码并做记录

    第二步:server.serve_forever()

    1、使用了事件驱动selectors模块,当有连接进来时,运行_handle_request_noblock()

    2、accept得到request,client_address

    3、创建一个线程来处理连接过来的请求

    更多

  • 相关阅读:
    c#将 1, 2, ..., 9共 9 个数字分成 3 组
    信息学院本科生创新项目总结
    Element-ui的使用
    fastmock接口管理
    mock安装与使用
    开闭原则
    里氏替换原则
    依赖倒置原则
    接口隔离原则
    单一职责原则
  • 原文地址:https://www.cnblogs.com/zj-luxj/p/7162220.html
Copyright © 2020-2023  润新知