Python SocketServer使用介紹
一、簡介:
SocketServer是python的一個網絡服務器框架,能夠減小開發人員編寫網絡服務器程序的工做量。python
SocketServer總共有4個server基類。服務器
TCPServer:負責處理TCP協議。網絡
UDPServer:負責處理UDP協議。多線程
UnixStreamServer:只適用於類unix平臺,不經常使用。併發
UnixDatagramServer:只適用於類unix平臺,不經常使用。框架
這4個類會同步處理每個request,也就是說只有當前的request處理完纔會處理下一個request,這種方式顯然很不合理,若是當前的request處理過慢的話就會致使「堵塞」。正確的處理方式應該是開闢新的進程或線程去處理不一樣的request,經過混合繼承ForkingMixIn或ThreadingMixIn類便可解決此問題。socket
二、建立SocketServer
使用SocketServer建立一個網絡服務程序只須要幾個簡單的步驟:oop
(1)、建立處理request的類,建立方法爲:繼承BaseRequestHandler類,並重載handle()方法。該方法將被回調用作處理當前接收到的request。post
注意:通常的作法是直接繼承StreamRequestHandler或者DatagramRequestHandler。好比:線程
class MyTCPHandler(SocketServer.StreamRequestHandler):
(2)、實例化一個server基類(好比TCPServer)的對象,併發服務器地址和處理request的類做爲參數傳入。
(3)、使用server基類對象調用handle_request()或serve_forever()方法,便可處理一個或多個request。
(4)、若是須要建立多進程或多線程的服務器程序,則能夠經過混合繼承ForkingMixIn或ThreadingMixIn類來實現,好比:
class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass //建立一個多線程的TCP服務器。
注意:ThreadingMixIn必需要放在TCPServer前面。
三、server類方法說明:
(1)、class SocketServer.BaseServer
這是全部類的超類,只定義接口,大部分均在子類中實現。
(2)、BaseServer.handle_request()
該方法用於處理單一的request。按順序調用get_request(), verify_request()和 process_request().
(3)、BaseServer.serve_forever(poll_interval=0.5)
循環輪詢處理request
(4)、BaseServer.address_family
協議簇信息,好比socket.AF_INET and socket.AF_UNIX
(5)、BaseServer.RequestHandlerClass
開發者自定義的用於處理request的類,每一個request都會對應實例化一個request handle 類進行處理。
(6)、BaseServer.server_address
服務器要監聽的地址和端口的二元組,好比(0.0.0.0,8080)
(7)、BaseServer.finish_request()
實例化開發者自定義request handle類,而後調用handle()方法處理當前的request。
(8)、
四、request handler類方法說明:
由用戶自定義並傳入SocketServer,由server類實例化來處理當前的request。須要注意的是:Request handler類必需要複寫handle()方法,其它方法也能夠複寫,但不作強制。
(1)、RequestHandler.handle()
開發者必須在此方法裏面實現對當前request的全部處理,在該方法裏面有幾個實例化的屬性能夠直接使用:self.request表明當前的request對象,self.client_address表明客戶端地址,self.server表明服務器對象。對於TCP連接,self.request是當前request的socket。self.rfile和self.wfile可分別用於讀取客戶端數據和向客戶端返回數據。
五、樣例代碼:
5.一、建立TCP類型的SocketServer:
import SocketServer class MyTCPHandler(SocketServer.BaseRequestHandler): #定義request handler類,從BaseRequestHandler類繼承 def handle(self): #複寫handle()方法,注意:該方法必須複寫,用於處理當前的request self.data = self.request.recv(1024).strip() #self.request是和客戶端鏈接的套接字,可直接使用 print "{} wrote:".format(self.client_address[0]) print self.data self.request.sendall(self.data.upper()) class MyTCPHandler(SocketServer.StreamRequestHandler): #定義request handler類,從StreamRequestHandler類繼承 def handle(self): self.data = self.rfile.readline().strip() #self.rfile/self.wfile是文件格式類型的socket,至關於對原始socket的封裝,讓讀寫網絡數據向讀寫文件同樣容易 print "{} wrote:".format(self.client_address[0]) print self.data self.wfile.write(self.data.upper()) if __name__ == "__main__": HOST, PORT = "localhost", 9999 server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler) #傳入監聽地址、端口號和request handler類 server.serve_forever() #啓動監聽處理request
5.二、建立UDP類型的SocketServer:
import SocketServer class MyUDPHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request[0].strip() socket = self.request[1] print "{} wrote:".format(self.client_address[0]) print data socket.sendto(data.upper(), self.client_address) if __name__ == "__main__": HOST, PORT = "localhost", 9999 server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler) server.serve_forever()
5.三、建立多線程類型的TCP SocketServer:
import socket import threading import SocketServer class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler): def handle(self): data = self.request.recv(1024) cur_thread = threading.current_thread() response = "{}: {}".format(cur_thread.name, data) self.request.sendall(response) class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):#繼承ThreadingMixIn表示使用多線程處理request,注意這兩個類的繼承順序不能變 pass def client(ip, port, message): sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.connect((ip, port)) try: sock.sendall(message) response = sock.recv(1024) print "Received: {}".format(response) finally: sock.close() if __name__ == "__main__": HOST, PORT = "localhost", 0 server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler) ip, port = server.server_address server_thread = threading.Thread(target=server.serve_forever) server_thread.daemon = True server_thread.start() print "Server loop running in thread:", server_thread.name client(ip, port, "Hello World 1") client(ip, port, "Hello World 2") client(ip, port, "Hello World 3") server.shutdown()