python socketserver框架解析

2022-02-18 07:53:05 字數 3565 閱讀 2519

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

print

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

客戶端:

#

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

我們建立乙個繼承自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之類的)而不同。

在這裡說乙個要注意的地方, 我使用了threadingtcpserver()類響應多個客戶端的連線, 但是當我閱讀這個類的原始碼的時候, 表示很疑惑啊!

class threadingtcpserver(threadingmixin, tcpserver): pass
這讓我很疑惑啊, 再看看呼叫:

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

這更疑惑, threadingtcpserver哪來的建構函式, 後來研究了一下, 原來當子類的某個函式或是屬性發生呼叫時, 如果不是過載了父類的方法或是屬性, 而且子類中沒有這個方法或是屬性, 就會去呼叫父類相對應的方法或是屬性, 於是上面的就是呼叫了tcpserver的初始化函式__init__以及serve_forever(), 隨後呼叫的是子類的request_handler函式

大概過程:

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...