標籤:socketserver 伺服器
socketserver
此模組簡化了socket的編寫。
1、它有一個基類,定義了如何建立串連。BaseServer提供了服務類介面,BaseServer使用了select建立了多線程。BaseServer下面有四個類:TCPServer、UnixStreamServer、UDPserver、UnixDatagramServer。
2、它還提供了請求處理類:定義了如何處理使用者資料。定義了三個方法setup\handler\finish,的介面,使用時,重新寫對應方法。
3、使用Forktheard和
BaseServer模組結構:
服務處理類方法:
|
作用
|
BaseServer
|
超類,提供了API,並利用select建立了多線程。不能直接調用它使用。
|
TCPServer
|
建立每個進程的socket,傳輸TCP資料。同時,也是一個基類。
|
UDPServer
|
傳輸UDP資料。 |
UnixStreamServer
|
Unix下使用
|
UnixDatagramServer |
Unix下使用
|
服務處理類BaseServer的方法
|
作用
|
fileno()
|
返回伺服器監聽通訊端的整數檔案描述符。通常用來傳遞給select.select(), 以允許一個進程監視多個伺服器。
|
handle_request()
|
處理單個請求。處理順序:get_request(), verify_request(), process_request()。 如果使用者提供handle()方法拋出異常,將調用伺服器的handle_error()方法。 如果self.timeout內沒有請求收到, 將調用handle_timeout()並返回handle_request()。
|
serve_forever(poll_interval=0.5) |
處理請求,直到一個明確的shutdown()請求。每poll_interval秒輪詢一次shutdown。忽略self.timeout。如果你需要做周期性的任務,建議放置在其他線程。 |
shutdown()
|
告訴serve_forever()停止。for python2.6。
|
address_family
|
地址簇。socket.AF_INET等
|
HandlerRequestClass
|
使用者提供的請求處理類,為每一個請求建立一個執行個體。
|
server_address
|
偵聽的伺服器位址。
|
socketSocket
|
伺服器上偵聽傳入的請求socket對象的伺服器。 |
|
|
下面方法可以被子類重載,它們對伺服器對象的外部使用者沒有影響。 |
finish_request() |
實際處理RequestHandlerClass發起的請求並調用其handle()方法。 常用。 |
get_request() |
接受socket請求,並返回二元組包含要用於與用戶端通訊的新socket對象,以及用戶端的地址。
|
handle_error(request, client_address) |
如果RequestHandlerClass的handle()方法拋出異常時調用。預設操作是列印traceback到標準輸出,並繼續處理其他請求。 |
handle_timeout() |
逾時處理。預設對於forking伺服器是收集退出的子進程狀態,threading伺服器則什麼都不做 |
process_request(request, client_address)
|
調用finish_request()建立RequestHandlerClass的執行個體。如果需要,此功能可以建立新的進程或線程來處理請求,ForkingMixIn和ThreadingMixIn類做到這點。常用。 |
server_activate() |
通過伺服器的建構函式來啟用伺服器。預設的行為只是監聽伺服器通訊端。可重載。 |
server_bind() |
通過伺服器的建構函式中調用綁定socket到所需的地址。可重載。 |
verify_request(request, client_address) |
返回一個布爾值,如果該值為True ,則該請求將被處理,反之請求將被拒絕。此功能可以重寫來實現對伺服器的存取控制。預設的實現始終返回True。client_address可以限定用戶端,比如只處理指定ip區間的請求。 常用。 |
|
|
服務處理類的變數(屬性):
|
作用
|
allow_reuse_address
|
是否允許地址重用,預設是False,可以在子類裡更改。
|
request_queue_size
|
請求隊列的大小。如果單個請求需要很長的時間來處理,伺服器忙時請求被放置到隊列中,最多可以放request_queue_size個。一旦隊列已滿,來自用戶端的請求將得到 “Connection denied”錯誤。預設值通常為5 ,但可以被子類覆蓋。 |
socket_type
|
伺服器使用的通訊端類型,socket.SOCK_STREAM和socket.SOCK_DGRAM等。 |
timeout
|
逾時時間。以秒為單位,或 None表示沒有逾時。如果handle_request()在timeout內沒有收到請求,將調用handle_timeout()。 |
|
|
請求處理類的方法:
|
作用
|
setup()
|
處理請求之前的方法,可以初始化。
|
handler()
|
處理請求的方法,處理與Client互動內容。
|
finish()
|
handler()處理完成後啟動並執行方法。用於釋放和清理。
|
|
|
#服務端:import socketserverclass Mysite(socketserver.BaseRequestHandler): # 必須繼承socketserver基類 def handler(self): # 重寫基類裡的handler()方法,在這個方法裡處理接收、發送請求 while True: recv_data = self.request.recv(1024) data = json.loads(recv_data.decode()) # 為什麼用json?,因為我喜歡。。這封裝數字、字元、列表等等資料類型通吃 print(data) if data.lower() == "exit": # 檢測到exit退出 print("用戶端退出!") break self.request.send(json.dumps(data.lower()).encode()) # 發送轉換小寫資料給用戶端,然後進入到下一個迴圈 my_server = socketserver.TCPserver(("localhost", 9999), Mysite) # 執行個體化socketserver,並傳送伺服器ip、port和子類my_server.serve_forever() # 用戶端import socket class Myclient(object): def __init__(obj): # 接收一個socket執行個體化的對象 self.conn = obj def handler(self,ip,prot): # 定義一個資料互動的方法 self.conn.connect((ip,port)) # 綁定連結,其它把它放在init方法裡是不是會更好? while Ture: # 迴圈發送、接收資料 cmd = input('輸入轉換的字元,exit退出!') if cmd.strip().lower() == 'exit': # 如果輸入EXIT退出 print('退出!') break self.conn.send(json.dumps(cmd).encode()) # 發送輸入的資料 recv_data = self.conn.recv(1024) # 接收伺服器轉換後的資料 data = json.loads(recv_data.decode()) # json解碼 print('轉換的:{}'.format(data)) my_socket = socket.socket() # 執行個體化socket對象my_client = Myclient(my_socket) # 執行個體化自訂類,並傳入執行個體化的socket對象my_client.handler("localhost",9999) # 調用資料互動方法"""以上代碼部落格裏手打,未經測試。 """
其它參考資料:
https://www.cnblogs.com/MnCu8261/p/5546823.html
https://www.cnblogs.com/sunailong/p/5058786.html
https://www.cnblogs.com/eric_yi/p/7701381.html
Python基礎:網路編程socketserver進階篇