SocketServer編程
類的繼承關係服務器
編程接口socket
#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()
小結ide
建立服務器須要幾個步驟: 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)
解決客戶端主動斷開鏈接問題ui
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'
總結spa