使用Python SocketServer快速實現多線程網絡服務器

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()
相關文章
相關標籤/搜索