在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ Python/ 改進詩歌下載服務(wù)器
小插曲 Deferred
異步編程模式與Reactor初探
使用Deferred新功能實現(xiàn)新客戶端
由twisted支持的客戶端
增強defer功能的客戶端
改進詩歌下載服務(wù)器
測試詩歌
更加"抽象"的運用Twisted
Deferred用于同步環(huán)境
輪子內(nèi)的輪子: Twisted和Erlang
Twisted 進程守護
構(gòu)造"回調(diào)"的另一種方法
Twisted 理論基礎(chǔ)
惰性不是遲緩: Twisted和Haskell
第二個小插曲,deferred
使用Deferred的詩歌下載客戶端
Deferreds 全貌
結(jié)束
取消之前的意圖
由Twisted扶持的客戶端
改進詩歌下載服務(wù)器
初識Twisted

改進詩歌下載服務(wù)器

新的服務(wù)器實現(xiàn)

這里我們要新寫一個Twisted版的服務(wù)器。然后,再來討論一些Deferred的新功能。

在第九、十部分,我們提出了詩歌轉(zhuǎn)換引擎這個概念。由于實現(xiàn)太過簡單,因此我們用隨機選擇來模擬了可能會出現(xiàn)的轉(zhuǎn)換失敗的情景。但如果轉(zhuǎn)換引擎位于服務(wù)器端,那么當服務(wù)器宕機就會出現(xiàn)真實的轉(zhuǎn)換失敗的情景了。

因此,在本節(jié)我們要實現(xiàn)一個詩歌樣式轉(zhuǎn)換服務(wù)器,然后在下一節(jié),我們會重寫詩歌下載客戶端使用這一服務(wù)來學習Deferred的新功能。

設(shè)計協(xié)議

到目前為止,服務(wù)器端與客戶端之間的交互都是單向的。但樣式轉(zhuǎn)換服務(wù)需要兩者進行雙向交互-客戶端將原始式樣的詩歌發(fā)送給服務(wù)器,然后服務(wù)器轉(zhuǎn)換格式并將其返回給對應(yīng)的客戶端。因此,我們需要使用或自己實現(xiàn)一個協(xié)議來實現(xiàn)這種交互。

我們設(shè)計服務(wù)器端可以提供若干種轉(zhuǎn)換服務(wù),讓客戶端來進行選擇。因此客戶端需要向服務(wù)器端發(fā)送兩部分信息:轉(zhuǎn)換方式與詩歌原始內(nèi)容。服務(wù)器只是將轉(zhuǎn)換格式之后的詩歌發(fā)送給客戶端。這里使用到了簡單的運程調(diào)用。

Twisted支持若干種能解決這個問題的協(xié)議:XML-RPC, Perspective Broker, AMP。

但介紹使用其中任何一種都需要大量的時間,因此我們使用自己實現(xiàn)的協(xié)議。我們約定客戶端發(fā)送內(nèi)容格式如下:

轉(zhuǎn)換方式.詩歌內(nèi)容

我們將其以netstring格式編碼,當然服務(wù)器回發(fā)的信息也是以netstring格式編碼。由于netstring使用了length-encoding,因此客戶端能夠識別出服務(wù)器沒有將完整詩歌回發(fā)的情況。如果你嘗試一下會發(fā)現(xiàn),之前的協(xié)議無法檢測到中途中斷傳輸?shù)那闆r。

代碼

新的服務(wù)器實現(xiàn)代碼在twisted-server-1/transformedpoetry.py中。首先,我們定義了一個TransformService類:

class TransformService(object):
    def cummingsify(self, poem):
        return poem.lower()

這里我們僅僅實現(xiàn)了一種轉(zhuǎn)換方法(與轉(zhuǎn)換方式同名),我們可以通過添加方法支持更多轉(zhuǎn)換方式。有一個重要的地方需要注意:格式轉(zhuǎn)換服務(wù)與具體協(xié)議的實現(xiàn)是完全分離的。將協(xié)議邏輯與服務(wù)邏輯分開是Twisted編程中常見的模式。這樣做可以通過多種協(xié)議實現(xiàn)同一種服務(wù),以增加代碼的重用性。

下面看看factory的實現(xiàn)代碼:

class TransformFactory(ServerFactory):
    protocol = TransformProtocol
    def __init__(self, service):
        self.service = service
    def transform(self, xform_name, poem):
        thunk = getattr(self, 'xform_%s' % (xform_name,), None)
        if thunk is None: # no such transform
            return None
        try:
            return thunk(poem)
        except:
            return None # transform failed
    def xform_cummingsify(self, poem):
        return self.service.cummingsify(poem)

factory提供了一個transform的函數(shù),protocol就是用它來處理客戶端連接發(fā)送的詩歌格式轉(zhuǎn)換請求的。

如果發(fā)現(xiàn)不存在客戶端請求的轉(zhuǎn)換方式或轉(zhuǎn)換失敗,那么返回None。和TransformService一樣,factory與具體的協(xié)議邏輯實現(xiàn)也是相互獨立的。

有一個地方需要引起注意:我們通過xfomr_前綴式方法來獲取服務(wù)方法。這種方法在Twisted中很常見,盡管前綴經(jīng)常發(fā)生變化,并且他們經(jīng)常是依賴獨立于factory的一個對象(如此處的 TransformService)??紤]到客戶端可以發(fā)送任意的transform方法名,這是一種防止客戶端蓄意使用惡性代碼來讓服務(wù)器端執(zhí)行的方法。這種方法也提供了實現(xiàn)由服務(wù)提供具體協(xié)議代理的機制。

下面是協(xié)議實現(xiàn)代碼:

class TransformProtocol(NetstringReceiver):
    def stringReceived(self, request):
        if '.' not in request: # bad request
            self.transport.loseConnection()
            return
        xform_name, poem = request.split('.', 1)
        self.xformRequestReceived(xform_name, poem)
    def xformRequestReceived(self, xform_name, poem):
        new_poem = self.factory.transform(xform_name, poem)
        if new_poem is not None:
            self.sendString(new_poem)
        self.transport.loseConnection()

在這個協(xié)議的實現(xiàn)中,我們通過繼承NetstringReceiver來利用了Twisted對netstrings的實現(xiàn)?;惡芎玫奶幚砹司幋a與解碼功能,我們需要做的就是實現(xiàn)stringReceived方法。換句話說,stringReceived接收的參數(shù)是客戶端編碼之后的詩歌,而無需我們再去添加額外的編碼信息。而且基類同樣管理著緩沖區(qū),即當一首詩歌完整接收完再進行解碼。

如果一切進展正常的話,我們會使用NetstringReceiver的 sendString方法來將格式轉(zhuǎn)換成功后的詩歌發(fā)送給客戶端。

注意我們是如何通過定義xformRequestReceived方法將收到的信息一步步推向更高的抽象層而實現(xiàn)了Twisted的模式。

一個簡單的客戶端

我們會在下一個部分來實現(xiàn)相應(yīng)的客戶端,這里使用一個簡單的腳本來實現(xiàn)客戶端,代碼位于twisted-server-1/transform-test中。如果你運行服務(wù)器端于11000端口:

python twisted-server-1/transformedpoetry.py --port 11000

相應(yīng)的運行腳本為:

./twisted-server-1/transform-test 11000

那么你會看到如下輸出(經(jīng)過netstring編碼):

15:here is my poem,

討論

在這個部分介紹了如下幾個方面內(nèi)容:

  1. 雙向通信
  2. 基于Twisted已有的協(xié)議實現(xiàn)新協(xié)議
  3. 將協(xié)議實現(xiàn)與服務(wù)功能實現(xiàn)獨立分開

雙向通信的基本機制是很簡單的。我們使用前面服務(wù)器端與客戶端使用的相同的技術(shù)來寫與讀數(shù)據(jù),唯一不同的是我們這次兩者都使用了(讀與寫)。當然,一個復(fù)雜的協(xié)議需要復(fù)雜的代碼來處理接收到的數(shù)據(jù)流與格式化輸出的信息。這也是為什么使用已經(jīng)存在的協(xié)議的原因。

如果你開始覺得寫簡單的協(xié)議已經(jīng)很上手了,那么最好就開始看看Twisted對不同協(xié)議的實現(xiàn)。盡管寫一些簡單的協(xié)議有助理解Twisted的編程風格,但在一個真實的程序中,最好是復(fù)用那些已經(jīng)實現(xiàn)并證明性能良好的協(xié)議。

最后一點是將協(xié)議解析邏輯與服務(wù)實現(xiàn)邏輯分開,這是Twisted編程中非常重要的一個模式。我們這個服務(wù)器程序只是一個演示,你可以想象一下真實的網(wǎng)絡(luò)服務(wù)是相當復(fù)雜的。通過將服務(wù)與協(xié)議邏輯分開,你可以通過復(fù)用已有的服務(wù)代碼來運行于其它的協(xié)議實現(xiàn)上。

圖27展示了一個格式轉(zhuǎn)換服務(wù)器通過兩種協(xié)議提供格式轉(zhuǎn)換服務(wù)(當然,我們的服務(wù)器只提供了一種協(xié)議):

http://wiki.jikexueyuan.com/project/twisted-intro/images/p12_server-21.png" alt="" />

雖然在圖27中使用了兩種協(xié)議,但他們也許只是幾個協(xié)議屬性不同而已,factory共享同一個服務(wù),這樣就實現(xiàn)了代碼的復(fù)用。

參考

本部分原作參見: dave @ http://krondo.com/?p=2101

本部分翻譯內(nèi)容參見楊曉偉的博客 http://blog.sina.com.cn/s/blog_704b6af70100qa5s.html