之前使用socket模組實現的網路程式設計都不能併發進行連線和通訊的, 即乙個客戶端需要等待伺服器和另乙個客戶端通訊完成後才能和服務端進行連線和通訊。
python3中提供有乙個高階內建模組socketserver來幫助我們進行併發的網路程式設計。
socketserver模組處理網路請求的功能,可以通過兩個主要的類來實現:乙個是伺服器類,乙個是請求處理類。
伺服器類 處理通訊問題,如監聽乙個套接字並接收連線等;
請求處理類 處理「協議」問題,如解釋到來的資料、處理資料並把資料發回給客戶端等。
這種實現將伺服器的實現過程和請求處理的實現過程解耦,這意味著我們可以將不同的伺服器實現和請求處理實現結合起來來處理一些定製的協議,例如乙個tcp伺服器類和乙個流請求處理類結合,處理基於tcp的網路請求。同時,也可以基於socketserver模組中的伺服器類和請求處理類,實現網路層之上應用層的伺服器和請求處理實現,例如基於tcp伺服器類實現http伺服器,基於流處理請求類實現http請求處理類等。
socketserver模組中定義了五種伺服器類
socketserver模組中定義了兩種mixin類, 用於支援非同步(fork用於建立多程序, thread使用者建立多執行緒)
socketserver模組伺服器類與mixin類組合得到
importsocketserver
addr = ('
127.0.0.1
', 8080)
class
myrequesthandler(socketserver.baserequesthandler):
defhandle(self):
print(self.request) #
套接字物件
print(self.client_address) #
客戶端的位址資訊
self.request.close()
tcpserver =socketserver.tcpserver(addr, myrequesthandler)
tcpserver.serve_forever()
我們從socketserver的baserequesthandler類中派生出乙個子類,並重寫handle()函式。在baserequest 類中,這個函式什麼也不做。在有客戶訊息進來的時候,handle()函式就會被呼叫。
importsocketserver
addr = ('
127.0.0.1
', 8080)
class
myrequesthandler(socketserver.baserequesthandler):
defhandle(self):
print(self.request[0]) #
客戶端傳送的訊息
print(self.request[1]) #
套接字鍍錫
(self.client_address)
self.request.close()
tcpserver =socketserver.udpserver(addr, myrequesthandler)
tcpserver.serve_forever()
如果要處理多連線問題,那麼有三種主要的方法能實現這個目的:分叉(forking)、執行緒(threading)以及非同步i/o(asynchronous i/o)。通過對socketserver伺服器使用混入類(mix-in class),派生程序和執行緒很容易處理。即使要自己實現它們,這些方法也很容易使用。它們確實有缺點:分叉佔據資源,並且如果有太多的客戶端時分叉不能很好分叉(儘管如此,對於合理數量的客戶端,分叉在現代的unix或者linux系統中是很高效的,如果有乙個多cpu系統,那系統效率會更高);執行緒處理能導致同步問題。使用socketserver框架建立分叉或者執行緒伺服器非常簡單
importsocketserver
addr = ('
127.0.0.1
', 8889)
class
server(socketserver.forkingmixin, socketserver.tcpserver):
pass
class
myrequesthandler(socketserver.baserequesthandler):
defhandle(self):
(self.request)
(self.client_address)
tcpserver =server(addr, myrequesthandler)
tcpserver.serve_forever()
建立udp分叉服務端同理即可
importsocketserver
addr = ('
127.0.0.1
', 8889)
class
server(socketserver.threadingmixin, socketserver.tcpserver):
pass
class
myrequesthandler(socketserver.baserequesthandler):
defhandle(self):
(self.request)
(self.client_address)
tcpserver =server(addr, myrequesthandler)
tcpserver.serve_forever()
建立udp多程序服務端同理即可
注意:threadingudpserver與threadingtcpserver類中的特有屬性:
高併發網路程式設計之epoll詳解
核心 使用者空間記憶體拷貝問題,select需要複製大量的控制代碼資料結構,產生巨大的開銷 select返回的是含有整個控制代碼的陣列,應用程式需要遍歷整個陣列才能發現哪些控制代碼發生了事件 select的觸發方式是水平觸發,應用程式如果沒有完成對乙個已經就緒的檔案描述符進行io操作,那麼之後每次s...
高併發網路程式設計之epoll詳解
核心 使用者空間記憶體拷貝問題,select需要複製大量的控制代碼資料結構,產生巨大的開銷 select返回的是含有整個控制代碼的陣列,應用程式需要遍歷整個陣列才能發現哪些控制代碼發生了事件 select的觸發方式是水平觸發,應用程式如果沒有完成對乙個已經就緒的檔案描述符進行io操作,那麼之後每次s...
網路程式設計 併發程式設計
01 網路程式設計 軟體開發架構 osi七層協議 乙太網協議 ip 埠 tcp udp 02 tcp的三次握手四次揮手理解及面試題 03 socket套接字使用 tcp連線通訊迴圈 tcp粘包問題 struct模組 tcp傳送檔案 04 udp協議 tcp udp基於socketserver的併發 ...