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


Python SocketServer使用介紹

1、簡介:

         SocketServerpython的一個網絡服務器框架,可以減少開發人員編寫網絡服務器程序的工作量。

SocketServer總共有4server基類。

TCPServer:負責處理TCP協議。

UDPServer:負責處理UDP協議。

UnixStreamServer:只適用於類unix平台,不常用。

UnixDatagramServer:只適用於類unix平台,不常用。

4個類會同步處理每一個request,也就是說只有當前的request處理完才會處理下一個request,這種方式顯然很不合理,如果當前的request處理過慢的話就會導致“堵塞”。正確的處理方式應該是開辟新的進程或線程去處理不同的request,通過混合繼承ForkingMixInThreadingMixIn類即可解決此問題。

2、創建SocketServer

         使用SocketServer創建一個網絡服務程序只需要幾個簡單的步驟:

1)、創建處理request的類,創建方法為:繼承BaseRequestHandler類,並重載handle()方法。該方法將被回調用做處理當前接收到的request

注意:一般的做法是直接繼承StreamRequestHandler或者DatagramRequestHandler。比如:

class MyTCPHandler(SocketServer.StreamRequestHandler):

2)、實例化一個server基類(比如TCPServer)的對象,並發服務器地址和處理request的類作為參數傳入。

3)、使用server基類對象調用handle_request()serve_forever()方法,即可處理一個或多個request

4)、如果需要創建多進程或多線程的服務器程序,則可以通過混合繼承ForkingMixInThreadingMixIn類來實現,比如:

class ThreadingTCPServer(ThreadingMixIn, TCPServer): pass //創建一個多線程的TCP服務器。

注意:ThreadingMixIn必須要放在TCPServer前面。

3server類方法說明:

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)、

4request handler類方法說明:

         由用戶自定義並傳入SocketServer,由server類實例化來處理當前的request。需要注意的是:Request handler類必須要復寫handle()方法,其它方法也可以復寫,但不做強制。

1)、RequestHandler.handle()

         開發者必須在此方法里面實現對當前request的所有處理,在該方法里面有幾個實例化的屬性可以直接使用:self.request代表當前的request對象,self.client_address代表客戶端地址,self.server代表服務器對象。對於TCP鏈接,self.request是當前requestsocketself.rfileself.wfile可分別用於讀取客戶端數據和向客戶端返回數據。

5、樣例代碼:

5.1、創建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.2、創建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.3、創建多線程類型的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()

 

執行結果:

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM