Twisted是用Python實現的基於事件驅動的網絡引擎框架,Twisted支持許多常見的傳輸及應用層協議,包括TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。就像Python同樣,Twisted也具備「內置電池」(batteries-included)的特色。Twisted對於其支持的全部協議都帶有客戶端和服務器實現,同時附帶有基於命令行的工具,使得配置和部署產品級的Twisted應用變得很是方便。python
Transports
Transports表明網絡中兩個通訊結點之間的鏈接。Transports負責描述鏈接的細節,好比鏈接是面向流式的仍是面向數據報的,流控以及可靠性。TCP、UDP和Unix套接字可做爲transports的例子。它們被設計爲「知足最小功能單元,同時具備最大程度的可複用性」,並且從協議實現中分離出來,這讓許多協議能夠採用相同類型的傳輸。Transports實現了ITransports接口,它包含以下的方法:react
write 以非阻塞的方式按順序依次將數據寫到物理鏈接上
writeSequence 將一個字符串列表寫到物理鏈接上
loseConnection 將全部掛起的數據寫入,而後關閉鏈接
getPeer 取得鏈接中對端的地址信息
getHost 取得鏈接中本端的地址信息
將transports從協議中分離出來也使得對這兩個層次的測試變得更加簡單。能夠經過簡單地寫入一個字符串來模擬傳輸,用這種方式來檢查。設計模式
Protocols
Protocols描述瞭如何以異步的方式處理網絡中的事件。HTTP、DNS以及IMAP是應用層協議中的例子。Protocols實現了IProtocol接口,它包含以下的方法:服務器
makeConnection 在transport對象和服務器之間創建一條鏈接
connectionMade 鏈接創建起來後調用
dataReceived 接收數據時調用
connectionLost 關閉鏈接時調用網絡
Reactor模式
Twisted實現了設計模式中的反應堆(reactor)模式,這種模式在單線程環境中調度多個事件源產生的事件到它們各自的事件處理例程中去。框架
Twisted的核心就是reactor事件循環。Reactor能夠感知網絡、文件系統以及定時器事件。它等待而後處理這些事件,從特定於平臺的行爲中抽象出來,並提供統一的接口,使得在網絡協議棧的任何位置對事件作出響應都變得簡單。異步
Deferreds
Deferred對象以抽象化的方式表達了一種思想,即結果還尚不存在。它一樣可以幫助管理產生這個結果所須要的回調鏈。當從函數中返回時,Deferred對象承諾在某個時刻函數將產生一個結果。返回的Deferred對象中包含全部註冊到事件上的回調引用,所以在函數間只須要傳遞這一個對象便可,跟蹤這個對象比單獨管理全部的回調要簡單的多。tcp
Deferred對象包含一對回調鏈,一個是針對操做成功的回調,一個是針對操做失敗的回調。初始狀態下Deferred對象的兩條鏈都爲空。在事件處理的過程當中,每一個階段都爲其添加處理成功的回調和處理失敗的回調。當一個異步結果到來時,Deferred對象就被「激活」,那麼處理成功的回調和處理失敗的回調就能夠以合適的方式按照它們添加進來的順序依次獲得調用。函數
異步版URL獲取器採用Deferred對象後的代碼以下:工具
from twisted.internet import reactor
import getPage
def processPage(page):
print page
def logError(error):
print error
def finishProcessing(value):
print "Shutting down..."
reactor.stop()
url = "http://google.com"
deferred = getPage(url) # getPage returns a Deferred
deferred.addCallbacks(success, failure)
deferred.addBoth(stop)
reactor.run()
在這個版本中調用的事件處理函數與以前相同,但它們都註冊到了一個單獨的Deferred對象上,而不是分散在代碼各處再以參數形式傳遞給getPage。
例子1:(簡單的tcp服務器實現)
server.py
#-*-coding:utf-8-*-
from twisted.internet import protocol,reactor
#from twisted.protocols.basic import LineReceiver
from time import ctime
import os,sys
from twisted.python import log #導入log
PORT = 23233
class TSServerProtocol(protocol.Protocol): #從Protocol派生出的TSSserverProtocol類
def connectionMade(self): #由於繼承了Protocol就可使用和自定義父類的方法了
clnt = self.clnt = self.transport.getPeer().host
log.msg('Client connected from %s' % clnt) #log用法
#self.sendData()
def dataReceived(self, data): #接受數據的方法
addr = self.transport.getHost().host
if data:
log.msg('Cmd received from %s : %s' % (self.clnt,data)) #data接收到的信息
self.transport.write('這是來自 %s ,的答覆:%s' %(addr,ctime())) #write發送
'''for i in os.listdir(os.getcwd()):
self.transport.write('[%s]%s' %(i,data))'''
def connectionLost(self,reason): #reason參數必需要寫否則報錯,當鏈接斷開時的調用
log.msg('鏈接斷開. ')
#log.msg('鏈接斷開. %s' % reason) # 加上reason會把斷開的錯誤信息答應出來
factory =protocol.Factory() #由於咱們上面只導入了protocol,因此這要把Factory函數導進來,每個protocol的實例都有一個工廠的引用,使用self.factory能夠訪問所在的工廠實例
factory.protocol = TSServerProtocol #當有請求進來時調用TSServerProtocol類
print 'waiting for connection......'
log.startLogging(sys.stdout) #以日誌形式打印到窗口
reactor.listenTCP(PORT,factory) #監聽請求
reactor.run() #啓動循環
client.py
#-*-coding:utf-8
from twisted.internet import protocol,reactor
HOST = 'localhost' #要鏈接的IP地址
PORT = 23233 #端口
class TSClntProtocol(protocol.Protocol): #同服務端同樣
def sendData(self): #定義一個發送數據的方法
data = raw_input('>')
if data:
print '....sending %s.......' %data
self.transport.write(data) #發送數據
else:
self.transport.loseConnection() #當沒有輸入時斷開鏈接
def connectionMade(self):
self.sendData() #調用方法
def dataReceived(self, data):
print data
self.sendData()
class TSClntFactory(protocol.ClientFactory):#個人理解是客戶端寫protocol.ClientFactory,服務端寫protocol.Factory
protocol = TSClntProtocol #同服務端同樣
clientConnectionLost = clientConnectionFailed = lambda self,connector,reason:reactor.stop()
reactor.connectTCP(HOST,PORT,TSClntFactory()) #跟服務端同樣reactor.run()