zoukankan      html  css  js  c++  java
  • 网络编程---SocketServer

    SocketServer

    类的继承关系

    编程接口

    #BaseServer代码
    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
        
        def finish_request(self, request, client_address):#处理请求的方法
            """Finish one request by instantiating RequestHandlerClass."""
            self.RequestHandlerClass(request, client_address, self)#RequestHandlerCLass构造

    #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
    #测试代码
    import socketserver
    import threading
    class MyHandler(socketserver.BaseRequestHandler):
        def handle(self):
            # super().handle()#可以不调用,父类handler什么都没有做
            print('-'*30)
            print(self.server)#服务
            print(self.request)#服务端连接请求的socket对象
            print(self.client_address)#客户端地址
            print(self.__dict__)
            print(self.server.__dict__)
    
            print(threading.enumerate())
            print(threading.current_thread())
            print('*'*30)
    
    addr = ('10.39.27.2',9999)
    server = socketserver.ThreadingTCPServer(addr,MyHandler)
    
    server.serve_forever()#永久

    import threading
    import logging
    import socketserver
    
    FORMAT="%(asctime)s %(threadName)s %(thread)d %(message)s"
    logging.basicConfig(level=logging.INFO,format=FORMAT)
    
    class MyHandler(socketserver.BaseRequestHandler):
        def handle(self):
            print(self.request)#服务端负责客户端连接请求的socket对象
            print(threading.enumerate())
            print(threading.current_thread())
    
            for i in range(3):
                data = self.request.recv(1024)
                logging.info(data)
            logging.info('========end===========')
    
    addr = ('10.39.27.2',9999)
    # server = socketserver.ThreadingTCPServer(addr,MyHandler)
    server = socketserver.TCPServer(addr,MyHandler)
    
    server.serve_forever()

    小结

    创建服务器需要几个步骤:
        1.从BaseRequestHandler类派生出子类,并覆盖其handler()方法来创建请求处理程序类,此方法将处理传入请求;
        2.实例化一个服务器类,传参服务器的地址和请求处理类;
        3.调用服务器示例的handler_request()或server_forver()方法;
        4.调用server_close()关闭套接字。

    实现EchoServer

    import threading
    from socketserver import ThreadingTCPServer,BaseRequestHandler
    import sys
    
    class EchoHandler(BaseRequestHandler):
        def setup(self):
            super().setup()
            self.event = threading.Event()#初始工作
    
        def handle(self):
            super().handle()
    
            while not self.event.is_set():
                data = self.request.recv(1024).decode()
                msg = "{} {}".format(self.client_address,data).encode()
                self.request.send(msg)
            print('End')
    
        def finish(self):
            super().finish()
            self.event.set()
    
    addr = ('0.0.0.0',9999)
    server = ThreadingTCPServer(addr,EchoHandler)
    server_thread  =threading.Thread(target=server.serve_forever,name='EchoServer',daemon=True)
    server_thread.start()
    
    try:
        while True:
            cmd = input('>>>')
            if cmd.strip() == 'quit':
                break
            print(threading.enumerate())
    except Exception as e:
        print(e)
    except KeyboardInterrupt:
        pass
    finally:
        print('exit')
        sys.exit(0)

    练习--改写ChatServer

    import threading
    from socketserver import ThreadingTCPServer,BaseRequestHandler
    import sys
    import logging
    
    FORMAT = "%(asctime)s %(threadName)s %(thread)d %(message)s"
    logging.basicConfig(level=logging.INFO,format=FORMAT)
    
    class ChatHandler(BaseRequestHandler):
        clients = {}
    
        def setup(self):
            super().setup()
            self.event = threading.Event()
            self.clients[self.client_address]  =self.request
    
        def handle(self):
            super().handle()
            while not self.event.is_set():
                data = self.request.recv(1024).decode()
                if data == 'quit':
                    break
                msg = "{} {}".format(self.client_address,data).encode()
                logging.info(msg)
                for c in self.clients.values():
                    c.send(msg)
            print('End')
    
        def finish(self):
            super().finish()
            self.clients.pop(self.client_address)
            self.event.set()
    
    addr = ('0.0.0.0',9999)
    server = ThreadingTCPServer(addr,ChatHandler)
    server_thread = threading.Thread(target=server.serve_forever,name='ChatServer',daemon=True)
    server_thread.start()
    
    try:
        while True:
            cmd = input('>>>')
            if cmd.strip() == 'quit':
                break
            print(threading.enumerate())
    except Exception as e:
        print(e)
    except KeyboardInterrupt:
        pass
    finally:
        print('exit')
        sys.exit(0)

    解决客户端主动断开连接问题

     

    import threading
    from socketserver import ThreadingTCPServer,BaseRequestHandler
    import sys
    import logging
    
    FORMAT = "%(asctime)s %(threadName)s %(thread)d %(message)s"
    logging.basicConfig(level=logging.INFO,format=FORMAT)
    
    class ChatHandler(BaseRequestHandler):
        clients = {}
    
        def setup(self):
            super().setup()
            self.event = threading.Event()
            self.clients[self.client_address]  =self.request
    
        def handle(self):
            super().handle()
            while not self.event.is_set():
                data = self.request.recv(1024).decode()
                print(data,'!!!!!!!!!!!!!!!!!!!!!')#增加
                if data == 'quit':
                    break
                msg = "{} {}".format(self.client_address,data).encode()
                logging.info(msg)
                for c in self.clients.values():
                    c.send(msg)
                print('###############')#增加
            print('End')
    
        def finish(self):
            super().finish()
            self.clients.pop(self.client_address)
            self.event.set()
    
    addr = ('0.0.0.0',9999)
    server = ThreadingTCPServer(addr,ChatHandler)
    server_thread = threading.Thread(target=server.serve_forever,name='ChatServer',daemon=True)
    server_thread.start()
    
    try:
        while True:
            cmd = input('>>>')
            if cmd.strip() == 'quit':
                break
            print(threading.enumerate())
    except Exception as e:
        print(e)
    except KeyboardInterrupt:
        pass
    finally:
        print('exit')
        sys.exit(0)

    #修改上述代码中handler()函数的一行代码即可
    将if data =='quit'
    修改为 if not data or data =='quit'

    总结

    做一枚奔跑的老少年!
  • 相关阅读:
    Code Forces 650 C Table Compression(并查集)
    Code Forces 645B Mischievous Mess Makers
    POJ 3735 Training little cats(矩阵快速幂)
    POJ 3233 Matrix Power Series(矩阵快速幂)
    PAT 1026 Table Tennis (30)
    ZOJ 3609 Modular Inverse
    Java实现 LeetCode 746 使用最小花费爬楼梯(递推)
    Java实现 LeetCode 745 前缀和后缀搜索(使用Hash代替字典树)
    Java实现 LeetCode 745 前缀和后缀搜索(使用Hash代替字典树)
    Java实现 LeetCode 745 前缀和后缀搜索(使用Hash代替字典树)
  • 原文地址:https://www.cnblogs.com/xiaoshayu520ly/p/11006131.html
Copyright © 2011-2022 走看看