(轉) Twisted :第十一部分 改進詩歌下載服務器

詩歌下載服務器html

到目前爲止,咱們已經學習了大量關於詩歌下載客戶端的Twisted的知識,接下來,咱們使用Twisted從新實現咱們的服務器端。利益於Twisted的抽象機制,接下來你會發現咱們前面已經幾乎所有學習到這部分知識了。其實現源碼在twisted-server-1/fastpoetry.py。之因此稱其爲fastpoetry是由於其並無任何延遲的傳輸詩歌。注意到,其代碼量比客戶端少多了。python

讓咱們一部分一部分地來看服務端的實現,首先是poetryProtocolreact

class PoetryProtocol(Protocol):
    def connectionMade(self):
        self.transport.write(self.factory.poem)
        self.transport.loseConnection()


如同客戶端的實現,服務器端使用Protocol來管理鏈接(在這裏,鏈接是由客戶端發起的)。這裏的Protocol實現了咱們的詩歌下載邏輯的服務器端。因爲咱們協議邏輯處理的是單向的,服務器端的Protocol只負責發送數據。若是你訪問服務器端,協議請求服務器在鏈接創建後當即發送詩歌,所以我實現了connectionMade方法,其會在Protocol中建立一個鏈接時被激活執行。git

這個方法告訴Transport作兩件事:將整首詩歌發送出去而後關閉鏈接。固然,這兩個動做都是同步操做。所以調用write函數也能夠說成「必定要將整首詩歌發送到客戶端」,調用loseConnection意味着「一旦將要求下載的詩歌發送完畢就關掉這個鏈接」。github

也許你看到了,Protocol是從Factory中得到詩歌內容的:服務器

class PoetryFactory(ServerFactory):
    protocol = PoetryProtocol
    def __init__(self, poem):
        self.poem = poem


這麼簡單!除了建立PoetryProtocol工廠的僅有的工做是存儲要發送的詩歌。網絡

注意到咱們繼承了ServerFactory而不是ClientFactory。這是由於服務器是要被動地監聽鏈接狀態而不是像客戶端同樣去主動的建立。咱們何以如此確定呢?由於咱們使用了listenTCP方法,其描述文檔聲明factory參數必須是ServerFactory類型的。socket

咱們在main函數中調用了listenTCP函數:函數

def main():
    options, poetry_file = parse_args()
    poem = open(poetry_file).read()
    factory = PoetryFactory(poem)
    from twisted.internet import reactor
    port = reactor.listenTCP(options.port or 0, factory,nterface=options.iface)
    print 'Serving %s on %s.' % (poetry_file, port.getHost())
    reactor.run()


其作了三件事:學習

1.讀取咱們要發呈現的詩歌

2.建立PoetryFactory並傳入這首詩歌

3.使用listenTCP來讓Twisted監聽指定的端口,並使用咱們提供的factory來爲每一個鏈接建立一個protocol

剩下的工做就是reactor來運轉事件循環了。你可使用前面任何一個客戶端來測試這個服務器。


討論

回憶下第五部分中的圖8與圖9.這兩張圖說明了一個協議在Twisted建立一個鏈接後如何建立一個協議並初始化它的。其實對於Twisted在其監聽的端口處接聽到一個鏈接以後的整個處理機制也是如此。這也是爲何connectTCPlistenTCP都須要一個factory參數的緣由。

咱們在圖9中沒有展現是的,connectionMake其實也是Protocol初始化的一部分。不管在哪兒都同樣(Dave是想說,connectionMade都會在Protocol初始化時執行),但咱們在客戶端處沒有用到這個方法。而且咱們在客戶端的協議實現中的方法並無在服務器處用到。所以,若是咱們有這個須要,能夠建立一個共享式的單一PoetryProtocol供客戶端與服務器端使用。這各方式在Twisted常常見到。例如,NetstringReceiver protocol即能讀從一個鏈接中讀也能向一個鏈接中寫netstrings

咱們略去了寫從低層來實現服務器端的內容,但咱們仍要來思考一下下面發生的事情。首先,調用listenTCP來告訴Twisted建立一個 listening socket 並將其添加到事件循環中。在 listening socket 有事件發生並不意味有數據要讀,而是說明有客戶端在等待鏈接本身。

Twisted會自動接受鏈接請求,並建立一個新客戶端式鏈接來鏈接客戶端與服務器(中間橋樑)。這個新的鏈接也要加入事件循環中,而且Twisted爲其建立了一個Transport與一個專門爲這個鏈接服務的PoetryProtocol。所以,Protocol實例老是鏈接到客戶端式的socket,而不是監聽式socket

咱們能夠在圖26中形象地看到這一結果:

第十一部分:改進詩歌下載服務器

26:服務器端的網絡鏈接

在圖中,有三個客戶端鏈接到服務器。每一個Transport表明一個client socket,加上listening socket總共是四個被select循環監聽的文件描述符(file descriptor).當一個客戶端斷開與其相關的transport的鏈接時,對應的PoetryProtocol也會被解引用並看成垃圾被回收。而PoetryFactory只要咱們還在監聽新的鏈接就會一直不停地工做(即PoetryFactory不會將PoetryProtocol會隨着一個鏈接的斷開而被銷燬)。

若是咱們提供的詩歌很短的話,那麼這些client socket與其相關的各類對象的生命期也就很短。但也有可能會是一臺至關繁忙的服務器以致於同時有千百個客戶端同時請求較長的詩歌。那不要緊,由於Twisted並無鏈接創建的限制。固然,當下載量持續的增長,在某個結點處,你會發現已經到達了OS的上限。對於那些高下載量的服務器,仔細的檢測與測試是天天都必須的工做。

而且Twisted在監聽端口的數量上亦無限制。實際上,一個單一的Twisted線程能夠監聽數個端口併爲其提供不一樣的服務(經過使用不一樣的factory做爲listenTCP的參數便可)。而且通過精心的設計,使用一個Twisted線程來提供多個服務仍是使用多個Twisted線程來實現能夠推遲到部署階段來作決定。

咱們這個版本的服務器有些功能是沒有的。首先,它沒法產生任何日誌來幫助咱們調試和分析網絡出現的問題。另外,服務器也不是作爲一個守護進程來運行,很容易經過ctrl+c來停止其執行。咱們將會在第十二部分來分析這部份內容。

相關文章
相關標籤/搜索