1. SocketServer.py
1.1 整體結構
在基類中調用并不實現的方法;類似于C++的純虛函數,強迫派生類實現。不一樣的是,如果派生類中不調用(派生類的用戶也不調用)該方法,那么派生類就可以不實現這個方法。
對某些函數提供一個空的實現,相當于JAVA的Adapter類,提供一個缺省實現。
RequestHandler的使用。并不是提供一個虛或者純虛函數來處理網絡請求,而是通過一個Handler類(或者函數,或者其它任何可以被調用的東西)來進行處理。
這就是傳說中的Strategy 模式。
優點:處理網絡請求和監聽、接受網絡請求相分離;松散耦合;無論哪個模塊都更容易重用。
MixIn的結構更加優雅。
1.2 BaseServer結構
可以被調用,不能被覆蓋的函數:
Ø
__init__(server_address,
RequestHandlerClass)
在 Base 中構造函數,保存
address 和 handler class,不調用任何函數。
在TCP中,構造 socket 對象,調用
server_bind和server_activate。
Ø
serve_forever()
循環處理每一個請求,直到世界末日 while True:
self.handle_request()
在
TCP中沒有覆蓋
在 UDP 中沒有覆蓋
Ø
handle_request() # if
you do not use serve_forever()
處理一個請求,在處理過程中,有可能產生阻塞。首先調用 get_request 獲得一個請求;然后調用verify_request對請求進行驗證;如果驗證成功,調用process_request對請求進行處理;如果處理過程中發生錯誤,調用handl_error處理錯誤,調用close_request釋放資源。
try:
request, client_address =
self.get_request()
except
socket.error:
return
if self.verify_request(request,
client_address):
try:
self.process_request(request,
client_address)
except:
self.handle_error(request,
client_address)
self.close_request(request)
在 TCP 中沒有覆蓋
在 UDP
中沒有覆蓋
Ø
fileno() -> int #
for select()
在 BaseServer中沒有實現
在 TCP
中調用 socket.fileno
在 UDP 中沒有覆蓋
可以被覆蓋的函數
Ø
server_bind()
在 Base
中沒有實現
在 TCP 中調用
socket.bind
在 UDP 中沒有覆蓋
Ø
server_activate()
在 Base
中沒有實現
在 TCP 中調用
socket.listen
在 UDP 中實現為空函數
Ø
get_request() -> request,
client_address
在 BaseServer 中沒有實現
在 TCP 中調用
socket.accept
在 UDP 中調用 socket.recvfrom
Ø
verify_request(request, client_address)
在 Base 中實現為空函數
在 TCP 中沒有覆蓋
Ø
server_close()
清理 server
所占用的資源,可以被覆蓋。
在 Base 中實現為空函數
在TCP中調用
socket.close
在 UDP 中沒有覆蓋
Ø
process_request(request,
client_address)
在 Base中調用
finish_request,然后 close_request。
在 TCP
中沒有覆蓋
在 UDP 中沒有覆蓋
Ø
close_request(request)
清理 request
所占用的資源,可以被覆蓋
在 Base 中實現為空函數
在 TCP
中調用 socket.close
在 UDP 中實現為空函數
Ø
handle_error()
在 Base
中打印錯誤信息。
在 TCP 中沒有覆蓋
在 UDP 中沒有覆蓋
向派生類提供的函數:
Ø
finish_request(request, client_address)
在 Base
中通過構造一個 RequestHandlerClass 實例來完成對request 的處理。
在 TCP 中沒有覆蓋
在 UDP
中沒有覆蓋
1.3 MixIn結構
為 Base
Server 提供多線程和多進程支持。
1.3.1 ForkingMinxIn提供多進程支持
在列表active_children中保存最大數量為max_children的進程。
在process_request中調用collect_children,檢查進程數量是否達到限制。如果進程數量達到限制,需要等待一個進程退出后,才會處理新請求。
在處理新的請求時,通過os.fork創建一個新進程:
1.
父進程
將子進程的oid加入active_children;調用close_request
2.
子進程
調用finish_request,如果發生錯誤,調用handle_error
1.3.2 ThreadingMixIn提供多線程支持
在process_request中創建新線程,在新線程中調用finish_request和close_request。支持daemon線程。
1.3.3 通過繼承使用
通過繼承某個MixIn和Server來達到目的。其中MixIn是第一基類,而Server是第二基類。MixIn中的process_request覆蓋Server的process_request。
1.4 RequestHandler結構
在BaseRequestHandler中有如下四個函數:
Ø __init__,構造函數
保存request, client_address, server;依次調用 setup, handle, finish。
這是一個Temeplate
Method Pattern,派生類不能覆蓋。
如果派生類要提供自己的構造函數,就應該不使用BaseRequestHandler提供的處理模式。
Ø setup,空函數
Ø handle,空函數,處理請求
Ø finish,空函數
在派生類StreamRequestHandler中:
Ø
覆蓋setup
根據request(對于TCP來說應該是socket對象)構造read file和write file
這樣派生類可以直接使用rfile和wfile進行數據讀寫
Ø
覆蓋finish
對輸出文件調用flush;關閉兩個文件對象
在派生類DatagramRequestHandler中:
Ø
覆蓋setup
將輸入流通過StringIO方法封裝成read file;構造一個空的輸出流StringIO() write
file
Ø
覆蓋finish
將輸出流中的數據發送到client_address
優點:無論是stream還是datagram方式,通過分別從這兩個類派生,都可以直接使用rfile和wfile進行數據讀寫。
posted on 2009-08-04 16:45
老馬驛站 閱讀(447)
評論(0) 編輯 收藏 引用 所屬分類:
python