socketserver框架是乙個基本的socket伺服器端框架, 使用了threading來處理多個客戶端的連線, 使用seletor模組來處理高併發訪問, 是值得一看的python 標準庫的原始碼之一
對於select網路框架的理解可以看 <>。socketserver框架採用了selector框架來供你選擇相適應的網路通訊框架, 比如select, poll, epoll等。有了這些網路框架我們就能處理高併發的網路訪問了. 先看看示例**吧:
#客戶端:coding: utf-8
import
socketserver
class
mytcphandler(socketserver.baserequesthandler):
"""the request handler class for our server.
it is instantiated once per connection to the server, and must
override the handle() method to implement communication to the
client.
"""def
handle(self):
#self.request is the tcp socket connected to the client
self.data = self.request.recv(1024).strip()
print("
{} wrote:
".format(self.client_address[0]))
(self.data)
#just send back the same data, but upper-cased
self.request.sendall(self.data.upper())
if__name__ == "
__main__":
host, port = "
localhost
", 9999
#create the server, binding to localhost on port 9999
#如果子類沒有某個方法或是屬性, 就回去父類中呼叫
with socketserver.threadingtcpserver((host, port), mytcphandler) as server:
#activate the server; this will keep running until you
#interrupt the program with ctrl-c
server.serve_forever()
#我們建立乙個繼承自baserequesthandler類的tcp請求處理類, 說白了這個類就是我們自己封裝的基於socket的recv()函式與send()函式的類, 而所謂的tcp請求處理類其實就是對socket伺服器端的bind, listen, accept等處理的封裝類, 而且這個封裝的並不是簡單的socket, 而是基於select或是epoll等網路框架的類, 我們呼叫這個類就能輕易地處理高併發的網路訪問. 其實認真閱讀原始碼, 你會發現整體的程式設計是基於事件驅動的, 事件驅動機制的三個要素: 訊息(事件)佇列, 訊息(事件)觸發, 事件迴圈。只不過socketserver框架的事件驅動機制就做到了socket的accept()方法那, 接下來的訊息接受(recv)與傳送(send)就沒有在做封裝成相應的事件來進行處理了。當然, 如果你需要處理http請求, 那麼此時的tcp請求處理類就不是處理send(),recv()了,而是根據http協議來解析請求,還得做各種封裝處理。總之,這個處理類就是因請求種類(主要是tcp,http,udp之類的)而不同。coding: utf-8
import
socket
sk =socket.socket()
sk.connect((
"127.0.0.1
", 9999)) #
主動初始化與伺服器端的連線
while
true:
send_data = input("
輸入傳送內容:")
sk.sendall(bytes(send_data, encoding="
utf8"))
if send_data == "
byebye":
break
accept_data = str(sk.recv(1024), encoding="
utf8")
print("".join(("
接收內容:
", accept_data)))
sk.close()
在這裡說乙個要注意的地方, 我使用了threadingtcpserver()類響應多個客戶端的連線, 但是當我閱讀這個類的原始碼的時候, 表示很疑惑啊!
class threadingtcpserver(threadingmixin, tcpserver): pass這讓我很疑惑啊, 再看看呼叫:
with socketserver.threadingtcpserver((host, port), mytcphandler) as server:這更疑惑, threadingtcpserver哪來的建構函式, 後來研究了一下, 原來當子類的某個函式或是屬性發生呼叫時, 如果不是過載了父類的方法或是屬性, 而且子類中沒有這個方法或是屬性, 就會去呼叫父類相對應的方法或是屬性, 於是上面的就是呼叫了tcpserver的初始化函式__init__以及serve_forever(), 隨後呼叫的是子類的request_handler函式#activate the server; this will keep running until you
#interrupt the program with ctrl-c
server.serve_forever()
大概過程:
tcpserver(__init__) → baseserver(__init__) → server_bind(繫結埠和位址) → server_activate(開啟監聽) → serve_forever(開啟迴圈) → selector.register(註冊, 呼叫基於selector的網路框架) → seletor.select() → _handle_request_noblock(開始處理請求) → get_request(呼叫底層的accept(), 接受客戶端的連線) → process_request(處理請求, 實際上是呼叫finish_request) → finish_request(呼叫客戶端的處理請求類(其實就是recv, send的一套操作, 這個類需要繼承自baserequesthandler類) → shutdown_request(關閉連線)
程式結果:
關於XUtils框架細解
感謝關注xuitls的最近一段時間給予的熱心反饋,xutils近期做了很多細節優化之後,功能和api已經穩定。1.9.6主要更新內容 bitmap載入動畫有時重複出現的問題修復,載入過程優化 http模組requestcallback等優化。詳細更新記錄見 commits master xutils...
自然框架 之「解耦」初探
解耦,在以前確實做不到,但是周四和 橫刀天笑 聊了之後,發現解耦是可以實現的。其實很簡單,只要弄出來乙個 實體類 就可以搞定了。如果是簡單的情況,那麼就讓表單控制項 全權負責 了,這時候是不需要些什麼 的,點點滑鼠,打幾個字就可以了。如果是有複雜的業務邏輯,那麼就可以定義乙個實體類,然後讓表單控制項...
仿掘金框架之listview全解(二)
我先把昨天那篇 仿掘金框架之listview全解 一 中提到的,我們可以通過這個專案練習到的知識點再列舉一下 續 仿掘金框架之listview全解 一 思路 在listview的觸控事件當中,我們判斷手觸控滑動大於一定的正值或者小於一定的負值,我們分別對應進行頭尾bar的隱藏和顯示的屬性動畫!ste...