• python网络编程-socketserver模块


    使用socketserver

    • 老规矩,先引入import socketserver
    • 必须创建一个类,且继承socketserver.BaseRequestHandler
    • 这个类中必须重写handle(self)函数负责和客户端进行交互,所以的交互都写这里面
    • 可以重写的方法
    #socketserver.BaseRequestHandler 类
        def setup(self):#请求进来之前的操作
            pass
     
        def handle(self):#处理请求的操作
            pass
     
        def finish(self):#请求结束后的后事
            pass
    

    我的客户端和服务端例子

    • 服务端
    import socketserver
     
    class MyTCPHandler(socketserver.BaseRequestHandler):
        def handle(self):
            #print(self.__dict__)#查看继承类中的属性和方法
            #print(self.server.__dict__)#查看ThreadingTCPServer中的属性和方法
            while True:
                try:
                    data = self.request.recv(1024)
                    #self.request.recv
                    print('收到命令:', data.decode())
                    cmd = data.decode()
                    # if not data:#socket中判断客户端是否断开的方法
                    #     print('客户端已断开')
                    #     break
                    cmd_res = os.popen(cmd).read()
                    if len(cmd_res) == 0:
                        cmd_res = 'has not this command...'
                    # 先发送结果长度给客户端判断
                    res_size = len(cmd_res.encode())
                    self.request.send(str(res_size).encode('utf-8'))
                    client_ack = self.request.recv(1024)  # 为防止粘包发生,这里给客户端在接收到数据大小后,发送一个消息给服务端确认
                    print(client_ack.decode())
                    self.request.send(cmd_res.encode('utf-8'))
                except ConnectionResetError as e:#在socketserver模块中,捕获ConnectionResetError判断客户端是否断开
                    print('连接断开:',e)
                    break
     
     
    if __name__ == "__main__":
        HOST, PORT = "localhost", 6512
     
        # Create the server, binding to localhost on port 9999
        server = socketserver.ThreadingTCPServer((HOST, PORT), MyTCPHandler)#多线程
        #server = socketserver.ForkingTCPServer((HOST, PORT), MyTCPHandler)#多进程,windows无法使用,linux适用
        # Activate the server; this will keep running until you
        # interrupt the program with Ctrl-C
        server.serve_forever()
    
    • 客户端
    import socket
     
    client = socket.socket()
    client.connect(('localhost',6512))
    while True:
        cmd = input('>>:')
        if len(cmd) == 0 : continue
        client.send(cmd.encode('utf-8'))
        cmd_res_size = client.recv(1024)#接收结果长度
        client.send('数据大小已收到,准备接收数据'.encode('utf-8'))#告诉服务器可以发送数据结果
        recv_size = 0
        cmd_res = b''
        while recv_size < int(cmd_res_size.decode()):
            data = client.recv(1024)
            recv_size += len(data)
            cmd_res += data
        else:
            print(cmd_res.decode())
            print('res is end...')
     
    client.close()
    

    父类socketserver.BaseRequestHandler中的__dict__

    {
        'request': <socket.socketfd=296,
        family=AddressFamily.AF_INET,#地址簇
        type=SocketKind.SOCK_STREAM,#socket类型
        proto=0,
        laddr=('127.0.0.1',
        6512),#服务端地址和端口
        raddr=('127.0.0.1',
        53668)>,#客户端地址和端口
        'client_address': ('127.0.0.1',
        53668),#客户端地址和端口
        'server': <socketserver.ThreadingTCPServerobjectat0x0000000001EC8AC8>
    }
    

    ThreadingTCPServer类中的__dict__

    {
        'server_address': ('127.0.0.1',
        6512),
        'RequestHandlerClass': <class'__main__.MyTCPHandler'>,
        '_BaseServer__is_shut_down': <threading.Eventobjectat0x0000000001EC8940>,
        '_BaseServer__shutdown_request': False,
        'socket': <socket.socketfd=200,
        family=AddressFamily.AF_INET,
        type=SocketKind.SOCK_STREAM,
        proto=0,
        laddr=('127.0.0.1',
        6512)>
    }
    RequestHandlerClass:
    {
        '__module__': '__main__',
        'handle': <functionMyTCPHandler.handleat0x0000000001ED31E0>,#指向我们自己定义的类
        '__doc__': None
    }
    _BaseServer__is_shut_down:
    {
        '_cond': <Condition(<unlocked_thread.lockobjectat0x0000000001E8D918>,
        0)>,
        '_flag': False
    }
    
  • 相关阅读:
    2-4 Vue中的属性绑定和双向数据绑定
    MySQL索引失效的几种情况
    MySQL索引失效的几种情况
    Linux实现MYSQl数据库的定时备份
    Linux实现MYSQl数据库的定时备份
    你还在 Select * 吗?
    你还在 Select * 吗?
    世界顶级的程序员们告诉你:这些书都是你应该读的
    世界顶级的程序员们告诉你:这些书都是你应该读的
    真正努力和不努力的程序员,发朋友圈究竟有什么不一样?
  • 原文地址:https://www.cnblogs.com/limich/p/7477046.html
Copyright © 2020-2023  润新知