abstrak:使用ThreadingMixIn類的特點: 在線程間共享應用的狀態(tài),與使用ForkingMixIn類相比避免進程間通信的復雜操作。代碼如下:#! /usr/bin/python import os import socket import threading import SocketS
使用ThreadingMixIn類的特點: 在線程間共享應用的狀態(tài),與使用ForkingMixIn類相比避免進程間通信的復雜操作。
代碼如下:
#! /usr/bin/python import os import socket import threading import SocketServer SERVER_HOST = 'localhost' SERVER_PORT = 0 BUF_SIZE = 1024 def client(ip, port, message): """A client to test threading mixin server""" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, port)) try: sock.sendall(message) response = sock.recv(BUF_SIZE) print "Client received: %s" % response finally: sock.close() class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): """An example of threaded TCP request handler """ def handle(self): data = self.request.recv(1024) current_thread = threading.current_thread() response = "%s: %s" % (current_thread.name, data) self.request.sendall(response) class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer): """Nothing add here, inherited everything from parenets""" pass if __name__ == '__main__': #run server server = ThreadedTCPServer((SERVER_HOST, SERVER_PORT), ThreadedTCPRequestHandler) ip, port = server.server_address # start a thread with the server, one thread per request server_thread = threading.Thread(target=server.serve_forever) # Exit the server thread when the main thread exits server_thread.daemon = True server_thread.start() print "Server loop running on thread: %s" % server_thread.name # run clients client(ip, port, "Hello from client1") client(ip, port, "Hello from client2") client(ip, port, "Hello from client3") #server cleanup server.shutdown()
注意1:在寫ThreadedTCPRequestHandler類中的方法handle的時候?qū)andle寫為了handler,結(jié)果在執(zhí)行程序后,顯示服務器返回給客戶端的信息為空,原因是handle方法是ThreadedTCPRequestHandler類所繼承的BaseRequestHandler類的類方法,由于BaseRequestHandler類的handle方法默認行為是啥也不做,所以要覆寫handle方法來處理接受客戶端消息,處理客戶端請求,如果寫為handler則在程序中默認調(diào)用了父類BaseRequestHandler的handle方法,但是啥也沒做,所以顯示服務器返回信息為空。
RequestHandler.handle()
This function must do all the work required to service a request. The default implementation does nothing. Several instance attributes are available to it; the request is available as self.request; the client address as self.client_address; and the server instance as self.server, in case it needs access to per-server information.
The type of self.request is different for datagram or stream services. For stream services, self.request is a socket object; for datagram services, self.request is a pair of string and socket. However, this can be hidden by using the request handler subclasses StreamRequestHandler or DatagramRequestHandler, which override the setup() and finish() methods, and provide self.rfile and self.wfile attributes. self.rfile and self.wfile can be read or written, respectively, to get the request data or return data to the client.
注意2,關于線程對象的setDaemon屬性,為True表示服務器線程為后臺線程,當沒有活動連接到后臺線程時,程序執(zhí)行完畢自動退出,當沒有活動的非后臺線程活動時,執(zhí)行完畢程序才會自動退出。對于本代碼,具體表現(xiàn)是如果在setDaemon為True的狀態(tài),不執(zhí)行服務器套接字的shutdown(),程序執(zhí)行完一樣會自動退出,而setDaemon為False的狀態(tài), 則一定要執(zhí)行shutdown(),程序才會自動終止。