Twisted簡介
Twisted 網絡編程框架是一種基於事件的網絡編程框架,用戶需要繼承特定的類,並重載其中的方法來處理網絡通信中可能出現的各種情況。一個典型的Twisted應用程序會建立至少一個協議,可以從twisted.internet.protocol.BaseProtocol類或其子類繼承。協議還需要實現數據的接收處理,即收到數據之後需要做出何種響應。比較簡單的Twisted應用程序可以繼承一個空的工廠,來自 twisted.internet.protocol.Factory或其子類。工廠至少應該指定protocol屬性,指向協議類。最後就是要啓動事件循環,根據連接方向的不同(客戶端或者服務端),可以選擇用reactor的connectXXX()或listenXXX()方法,然後執行reactor.run()啓動事件循環。
Twisted網絡模型基本組成
反應器(reactor)
用來執行事件循環,分發事件處理等等,每個應用程序中一般只能啓動一個reactor。可以把反應器(reactor)想象爲Twisted程序的中樞神經,reactor根據平臺的不同,提供了不同的實現,在使用的時候,可以根據平臺的不同,選擇不同的reactor。除了分發事件循環之外,反應器還做很多重要的工作:定時任務、線程、建立網絡連接、監聽連接。
協議(protocol)
用來完成與一個已經連接成功的主機的交互功能,主要有數據的接收和發送功能。連接的斷開事件也可以在這裏處理。注意是在連接建立之後protocol纔開始負責下面的工作的。從Protocol類繼承就可以完成協議的基本處理了,包括連接的建立和斷開事件,還有數據接收事件。
工廠(factory)
負責與一個協議protocol的啓動和關閉功能,而且還負責在連接成功時生成一個協議protocol對象,(by gashero)用於與遠程主機的交互功能。factory如名字所暗示的,是抽象工廠。在Twisted中把一個工廠對象綁定到特定的端口中,當連接到來,Twisted使用該工廠創建工廠指定的protocol對象,protocol對象表明了連接的處理流程(協議),每個protocol對象按照預定的協議處理連接,當連接關閉後銷燬。
reactor模型
啓動事件循環
from twisted.internet import reactor
reactor.run()
停止時間循環
from twisted.internet import reactor
reactor.stop()
設置定時事件
from twisted.internet import reactor
from twisted.internet import task
import time
def printtime():
print"Cuttent time is",time.strftime("%H:%M:%S")
def stopreactor():
print"Stopping reactor"
reactor.stop()
lc = task.LoopingCall(printtime)#每隔1s執行一次printtime函數
lc.start(1)
reactor.callLater(5,stopreactor)#5s後執行stopreactor函數
print"Running the reactor..."
reactor.run()
print "Reactor stopped."
protocol模型
BaseProtocol類
所有協議類的基類是 twisted.internet.protocol.BaseProtocol,但是一般使用其子類,不同的協議子類提供了不同的數據接收方法。
class BaseProtocol:
connected=0 #是否已經連接了
transport=None #用於數據發送的傳輸對象
def makeConnection(self,transport):
#建立連接的方法,不是事件方法,一般不要重載
def connectionMade(self):
#連接成功事件,可重載可以看到BaseProtocol可以理解爲一個虛基類,實現的功能十分簡陋
Protocol類
實際的應用程序一般也不是直接繼承BaseProtocol來實現協議,而是繼承Protocol類,Protocol類提供了基本完善的協議功能。
class Protocol(BaseProtocol):
def dataReceived(self,data):
#接收到數據事件,可重載
def connectionLost(self,reason=connectionDone):
#連接斷開事件,可重載,依靠reason區分斷開類型
factory模型
Factory類
所有工廠的基類是twisted.internet.protocol.Factory,這個類定義了三個方法。Factory類中最重要的部分就是協議protocol屬性,將這個屬性設置爲一個協議類(注意不是協議對象),就可以將這個工廠設置爲對應協議的工廠了。
class Factory:
@classmethod
def forProtocol(cls, protocol, *args, **kwargs):
爲給定協議創建一個工廠factory
protocol 一個協議子類
args 給工廠的參數
kwargs 工廠的關鍵字參數
返回一個連接到的協議工廠實例
def logPrefix(self):
描述這個工廠的日誌消息
def doStart(self):
確保啓動factory時被調用,用戶自己不應該調用這個函數。
def doStop(self):
確保停止factory時被調用,用戶自己不應該調用這個函數。
def startFactory(self):
在開始監聽端口或連接之前被調用,它只會被調用一次,即使這個工廠被多個端口連接。這個可以用來執行一個不是連續的任務,最好是推遲到實際運行,
比如連接到數據庫,打開文件等
def stopFactory(self):
在停止監聽端口或連接之前被調用。這可以覆蓋執行“關閉”任務如斷開數據庫連接、關閉文件等。例如,它會被稱爲應用程序關閉之前,如果是連接到一個端口。
用戶代碼不能直接調用這個函數。
def buildProtocol(self, addr):
爲每一個新連接創建一個protocol子類的實例
返回的實例將處理傳入服務器上輸入連接,和一個指向創建工廠的屬性。另外, None可能回到立即關閉新連接。
重寫這個方法來改變協議創建實例。
參數 addr 一個對象實現 twisted.internet.interfaces.IAddress
factory分類
1.服務器factory
服務器factory繼承自Factory,而沒有任何修改,定義如下:
class ServerFactory(Factory):
2.客戶端factory
class ClientFactory(Factory):
def startedConnecting(self,connector):
#當一個連接開始時調用
def clientConnectionFailed(self,connector,reason):
#當一個連接失敗時調用
def clientConnectionLost(self,connector,reason):
#當一個連接斷開時調用
以上方法都傳遞了一個connector對象,這個對象有如下方法可用:
connector.stopConnection() #關閉會話
connector.connect() #一般在連接失敗時用於重新連接
連接器
連接器指客戶端用來連接的包裝。twisted.internet.protocol.ClientCreator是一個連接器,用來連接遠程主機,接口定義如下。
class ClientCreator:
def __init__(self,reactor,protocolClass,*args,**kwargs):
def connectTCP(self,host,port,timeout=30,bindAddress=None):
def connectUNIX(self,address,timeout=30,checkPID=0):
def connectSSL(self,host,port,contextFactory,timeout=30,bindAddress=None):
三個連接方法都是返回Deferred對象作爲Protocol實例,在不需要工廠時可以直接使用這個類來產生僅使用一次的客戶端連接。這時,協議對象之間沒有共享狀態,也不需要重新連接。