SocketServer源碼學習(一)

来源:https://www.cnblogs.com/zhaof/archive/2018/04/19/8878836.html
-Advertisement-
Play Games

SocketServer其實是對socket更高級的封裝正如官網上說的:The socketserver module simplifies the task of writing network servers. 我們可以先打開以下SocketServer的源碼,看一下源碼中整體的框架 從上圖我們 ...


SocketServer其實是對socket更高級的封裝正如官網上說的:
The socketserver module simplifies the task of writing network servers.

我們可以先打開以下SocketServer的源碼,看一下源碼中整體的框架

從上圖我們可以看出SocketServer主要被抽象為兩個主要的類:
BaseServer類,用於處理連接相關的網路操作
BaseRequestHandler類,用於實際處理數據相關的操作

SocketServer還提供了兩個MixIn類:ThreadingMinxIn和ForkingMixinl
用於擴展server,實現多進程和多線程

下麵從會從這幾個主要的類開始做一個整體的分析,瞭解SocketServer的處理流程

 

BaseServer

先列一下這裡所包含的方法:
server_activate
serve_forever
shutdown
service_actions
handle_request
handlerequest_noblock
handle_timeout
verify_request
process_request
server_close
finish_request
shutdown_request
close_request
handle_error

先看一下BaseServer的初始化函數,其實並沒有過多的參數,主要就是實現了創建server對象,並初始化server地址和處理請求的類:RequestHandlerClass

def __init__(self, server_address, RequestHandlerClass):
    """Constructor.  May be extended, do not override."""
    self.server_address = server_address
    self.RequestHandlerClass = RequestHandlerClass
    self.__is_shut_down = threading.Event()
    self.__shutdown_request = False

serve_forever

先看一下源碼內容如下:

def serve_forever(self, poll_interval=0.5):
    """Handle one request at a time until shutdown.

    Polls for shutdown every poll_interval seconds. Ignores
    self.timeout. If you need to do periodic tasks, do them in
    another thread.
    """
    self.__is_shut_down.clear()
    try:
        # XXX: Consider using another file descriptor or connecting to the
        # socket to wake this up instead of polling. Polling reduces our
        # responsiveness to a shutdown request and wastes cpu at all other
        # times.
        with _ServerSelector() as selector:
            selector.register(self, selectors.EVENT_READ)

            while not self.__shutdown_request:
                ready = selector.select(poll_interval)
                if ready:
                    self._handle_request_noblock()

                self.service_actions()
    finally:
        self.__shutdown_request = False
        self.__is_shut_down.set()

當創建server對象之後,我們會使用server對象開啟一個無限迴圈,即調用serve_forever,
下麵是它的源碼,接受一個參數poll_interval,用於表示select輪詢的時間,然後進入一個死迴圈,用select方法進行網路IO的監聽,這裡通過調用selector.register(self, selectors.EVENT_READ)進行了註冊,當ready有返回是,表示有IO連接或者數據,這個時候會調用_handle_request_noblock
接著看一下_handle_request_noblock源碼

handlerequest_noblock

源碼內容如下:

def _handle_request_noblock(self):
    """Handle one request, without blocking.

    I assume that selector.select() has returned that the socket is
    readable before this function was called, so there should be no risk of
    blocking in get_request().
    """
    try:
        request, client_address = self.get_request()
    except OSError:
        return
    if self.verify_request(request, client_address):
        try:
            self.process_request(request, client_address)
        except:
            self.handle_error(request, client_address)
            self.shutdown_request(request)
    else:
        self.shutdown_request(request)

handlerequest_noblock方法即開始處理一個請求,並且是非阻塞。該方法通過get_request方法獲取連接,具體的實現在其子類。一旦得到了連接,調用verify_request方法驗證請求。驗證通過,即調用process_request處理請求。如果中途出現錯誤,則調用handle_error處理錯誤,以及shutdown_request結束連接。

而verify_request中預設直接返回True,所以當驗證通過後講調用process_request

process_request

源碼內容如下:

def process_request(self, request, client_address):
    """Call finish_request.

    Overridden by ForkingMixIn and ThreadingMixIn.

    """
    self.finish_request(request, client_address)
    self.shutdown_request(request)

就像源碼中描述的那樣:Overridden by ForkingMixIn and ThreadingMixIn.
process_request方法是mixin的入口,MixIn子類通過重寫該方法,進行多線程或多進程的配置。調用finish_request完成請求的處理,同時調用shutdown_request結束請求。繼續查看finish_request

finish_request

源碼內容如下:

def finish_request(self, request, client_address):
    """Finish one request by instantiating RequestHandlerClass."""
    self.RequestHandlerClass(request, client_address, self)

關於請求的部分到這裡就已經處理完畢,接下來是要對數據的處理,finish_request方法將會處理完畢請求。創建requestHandler對象,並通過requestHandler做具體的處理。

BaseRequestHandler

就像我們前面說的:
BaseServer類,用於處理連接相關的網路操作
BaseRequestHandler類,用於實際處理數據相關的操作

還是從初始化函數里看源碼:

def __init__(self, request, client_address, server):
    self.request = request
    self.client_address = client_address
    self.server = server
    self.setup()
    try:
        self.handle()
    finally:
        self.finish()

該類會處理每一個請求。初始化對象的時候,設置請求request對象。然後調用setup方法,子類會重寫該方法,用於處理socket連接。接下來的將是handler和finish方法。所有對請求的處理,都可以重寫handler方法。

SocketServer的一個服務端的簡單例子

直接上代碼了:

import socketserver


class MyTCPHandler(socketserver.BaseRequestHandler):
    def handle(self):
        while True:
            try:
                self.data = self.request.recv(1024).strip()
                print("{} wrote:".format(self.client_address))
                print(self.data)
                self.request.sendall(self.data.upper())
            except ConnectionResetError as e:
                print(e)
                break

if __name__ == '__main__':
    host,port = "127.0.0.1",9999
    server = socketserver.TCPServer((host,port),MyTCPHandler)
    server.serve_forever()

通過對源碼的分析我們已經知道了對數據的處理部分都是在BaseRequestHandler這個類中,而我們的主要處理邏輯也就是在這部分,所以我繼承了這個類,重寫了handle方法

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • @ResponseBody 在返回的數據不是html標簽的頁面,而是其他某種格式的數據時(如json、xml等)使用; 不在springMvc中配置json的處理的話,我們通常會在Controller層中獲取到數據之後進行類型轉化,將數據轉成json字元串,比如調用fastjson進行轉化,如下 這 ...
  • 手把手教你寫網路爬蟲(4) 作者:拓海 摘要:從零開始寫爬蟲,初學者的速成指南! 封面: 上期我們理性的分析了為什麼要學習Scrapy,理由只有一個,那就是免費,一分錢都不用花! 咦?怎麼有人扔西紅柿?好吧,我承認電視看多了。不過今天是沒得看了,為了趕稿,又是一個不眠夜。。。言歸正傳,我們將在這一期 ...
  • 在進行網頁數據抓取時我們要先安裝一個模塊 requests 通過終端安裝如下圖 因為我之前安裝過了,所以不會顯示安裝進度條,安裝也非常簡單,如果你配置好環境變數的話,你只需要執行以下命令 如果提示要升級,就按下麵升級pip 安裝完模塊後我們正式開始進行數據爬取 先說一下requests的用法,導入這 ...
  • 用for迴圈對無序數組進行排序輸出。 public class BubbleSort{ public static void main (String [] args){ int a[] = {21,9,45,17,33,72,50,12,41,39}; for (int i=a.length; - ...
  • MyBatis—Spring 項目 目前大部分的 Java 互聯網項目,都是用 Spring MVC + Spring + MyBatis 搭建平臺的。 使用 "Spring IoC" 可以有效的管理各類的 Java 資源,達到即插即拔的功能;通過 "Spring AOP" 框架,資料庫事務可以委托 ...
  • 內容:日曆對象獲取時間,設置時間,日期偏移 通過工廠化獲得對象。getInstance();get() 獲取時間信息 美國的星期是從星期天開始的,所以會有點問題set()設置方法,設置時間 //解答三月一日的前一天就是 Calendar c = Calendar.getInstance(); int ...
  • 集合的迭代器 任何集合都有迭代器。 任何集合類,都必須能以某種方式存取元素,否則這個集合容器就沒有任何意義。 迭代器,也是一種模式(也叫迭代器模式)。在java中它是一個對象,其目的是遍歷並選中其中的每個元素,而使用者(客戶端)無需知道裡面的具體細節。迭代器要足夠的“輕量”——創建迭代器的代價小。所 ...
  • Github項目地址: https://github.com/JtvDeemo/elementary arithmetic PSP ||||| |: |: |: |: | | PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...