Twisted Network Programming Essentials(中文渣翻一)
第一章 介紹Twisted
1.1 開始
在你會用Twisted建立app之前,你需要下載安裝Twisted和它的環境。這一章的主要任務就是幫助你學會安裝Twisted。
Twisted需要python2.6或者2.7。支援python3的版本還在構建中。
安裝Twisted
首先:你需要下載Twisted。下載和說明以及相應的版本都可以在https://twistedmatrix.com/trac/找到(建議各位去官網看看)。想要啟動Twisted裡面的其他功能,你需要安裝一些額外的包。
linux上安裝
所有流行的Linux釋出版本都內建了一個python-twisted安裝包和對應版本的環境支援。如果要在dpkg-based系統上安裝,用
apt-get install python-twisted
正在rmp-based系統,用
yum install python-twisted
就這麼簡單。
如果你要使用Twisted的SSL或者SSH功能,可以用python-openssl和python-crypto來獲取。
Windows上安裝
Twisted對於Windows有32位和64位,如果你不確定,就安裝32位的。
去官網上下載Twisted吧https://twistedmatrix.com/trac/。
測試你的Twisted
為了驗證你的Twisted沒有損壞,在python下這樣寫
importtwisted print(twisted.__version__)
驗證你已經安裝了pyOpenSSL來使用Twisted的SSL功能,用以下程式碼測試
import OpenSSL import twisted.internet.ssl twisted.internet.ssl.SSL
如果你沒有看到報錯,你已經成功地為你的Twisted添加了SSL支援。
如果你為了使用Twisted的SSH已經安裝了PyCrypto,可以這樣驗證
import Crypto import twisted.conch.ssh.transport twisted.conch.ssh.transport.md5
如果沒有看到錯誤就一切OK。
恭喜你,你已經知道了怎麼安裝Twisted開始你的程式設計之路了。
1.2建立一個基礎的客戶端和伺服器
學習Twisted應用的最好方法就是實踐一些小例子。這一章會為你介紹reactor迴圈,資訊傳輸和在客戶端伺服器上執行TCP協議。
A 基於TCP的回顯客戶端和伺服器
請瀏覽一下examples2-1和2-2。伺服器建立了TCO連線而且監聽了固定埠,而且為它受到的所有資訊進行回顯。客戶端負責連線伺服器,傳送訊息,接受迴應和斷開連線。
#Example 2-1 echoserver.py
from twisted.internet import protocol,reactor
class Echo(protocol.Protocol):
def dataReceived(self, data):
print('receive: ',data)
self.transport.write(data)
class EchoFactory(protocol.Factory):
def buildProtocol(self, addr):
print('addr:',addr)
return Echo()
reactor.listenTCP(8001,EchoFactory())
reactor.run()
#Example 2-2 echoclient.py
from twisted.internet import reactor,protocol
class EchoClient(protocol.Protocol):
def connectionMade(self):
print('send msg')
self.transport.write(b"Hello,world!")
def dataReceived(self, data):
print('receive msg:',data)
self.transport.loseConnection()
class EchoClientFactory(protocol.ClientFactory):
def buildProtocol(self, addr):
return EchoClient()
def clientConnectionLost(self, connector, reason):
print("conn lost")
reactor.stop()
def clientConnectionFailed(self, connector, reason):
print('conn failed')
reactor.stop()
reactor.connectTCP("127.0.0.1",8001,EchoClientFactory())
reactor.run()
為了測試這兩個指令碼,首先在命令列裡執行echoserver.py。這樣就會在本地8001埠上執行一個TCP服務。之後在第二個命令列裡執行echoclient.py。
addr: IPv4Address(type='TCP', host='127.0.0.1', port=61264) receive: b'Hello,world!' send msg receive msg: b'Hello,world!' conn lost
啊哈,你已經完成了你的第一個非同步事件驅動的Twisted應用。讓我們看看它的每一步的具體實現是怎樣的吧。
事件驅動程式
回顯伺服器和客戶端都是事件驅動程式,更流行的說法是,Twistd是一個非同步驅動引擎,這是什麼意思呢?
在一個非同步驅動程式裡,程式執行由外部事件驅動。最明顯的特徵是每當事件來臨通過一個loop迴圈和使用callback來觸發行為。把這個結構和其他兩種相同的模型相比:單執行緒和多執行緒。
通過執行任務來顯示三個模型的不同。程式有三個任務需要完成,每一個任務都需要等待IO結束,在這之前會阻塞。
在單執行緒裡,任務是線性執行的。如果一個任務阻塞,所有的人物都必須等待,這顯然是糟糕的方法。
在多執行緒裡,三個阻塞任務在三個執行緒裡執行,可以在一個或者多個處理器上執行。這樣允許一些執行緒阻塞,另一些執行,顯然比單執行緒有效率。然而,必須編寫程式碼維護多個執行緒併發訪問共享資源,否則會出現一些莫名其妙的BUG。
非同步版本把三個任務交叉在一個執行緒內,在執行IO或者其他耗時的操作時,會通過loop回撥註冊的事件,在IO完成的時候繼續執行。事件雲鬟輪詢事件,並且在事件來臨的時候分發給等待著他們的回撥函式。這允許程式在不使用額外執行緒的情況下取得進展。
非同步驅動同時享受了多執行緒的並行和單執行緒的簡單操作。
Reactor反應堆
Twisted的核心其實就是反應堆事件輪詢。reactor知曉網路,檔案系統和計時器的事件。它會等待並且分發這些事件給相應的處理器。Twisted負責把特定的行為抽象化,並且正確地使用底層的非阻塞API。Twisted存在一個通用介面來讓網路堆疊中任何位置的事件很容易地獲得相應。
reactor本質
while True: timeout=time_until_next_timed_event() events=wait_for_events(timeout) events+=timed_events_until(now()) for event in events: event.process()
在我們上邊編寫的客戶端和伺服器中,reactor通過監聽TCP和連線TCP來負責註冊回撥,以便在8001埠上可以從TCP套接字讀取資料時候得到通知。
在這些回撥被註冊之後,我們開始了反應堆的事件迴圈reactor.run()。一旦開始,reactor就會排程事件一直到得到反映或者一直執行下去,除非你stop它。
Transports通訊
一個transport代表著網路兩端的連線。Transports展示了連線的細節:舉個例子,這是面向tcp,udp,unix套接字換你是序列介面的例項?Transports執行了ITransport介面,它有以下方法:
write
以非阻塞的方式把資料寫入物理連線
writeSequence
以字串列表的方式寫入物理連線。在使用面向行的協議的時候有效。
loseConnection
寫入所有資料,之後斷開連線
getPeer
獲得連線端的地址
getHost
和getPeer一樣,但是返回的是本地的地址
在回顯的例子裡,兩端傳送資料用了write方法。客戶端在接受到訊息之後終止了連結。
Protocols
protocols展現了怎樣非同步執行程式。Twisted內建了許多流行的協議,包括HTTP,TELNET,DNS,IMAP。協議執行了IProtocol介面,它有以下方法:
makeConnection
通過兩端的傳輸建立一個連線
connectionMade
連線到另一個端點的時候呼叫
dataReceived
接收到資料的時候呼叫
connectionLost
斷開連線的時候呼叫
在我們的回顯例子裡用了protocol.Protocol作為基類。connectTCP建立了一個TCP連線而且為接收資料註冊了回撥方法。
Protocol Factories
永續性的資料被儲存在工廠裡,它繼承protocol.Factory或者ClientFactory。裡邊的buildrotocol方法為每一個新的連線建立一個協議,而且被註冊到reactor裡邊。
對工廠和協議的解耦讓一個型別的transport擁有許多協議成為可能,而且便於測試。