Twsited異步網絡框架
Twisted是一個事件驅動的網絡框架,其中包含了諸多功能,例如:網絡協議、線程、數據庫管理、網絡操作、電子郵件等。
事件驅動
簡而言之,事件驅動分爲二個部分:第一,註冊事件;第二,觸發事件。
例:程序一
#!/usr/bin/env python
# -*- coding:utf-8 -*-
# event_drive.py
event_list = []
def run():
for event in event_list:
obj = event()
obj.execute()
class BaseHandler(object):
"""
用戶必須繼承該類,從而規範所有類的方法(類似於接口的功能)
"""
def execute(self):
raise Exception('you must overwrite execute')
程序二,動用程序一
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from source import event_drive
class MyHandler(event_drive.BaseHandler):
def execute(self):
print 'event-drive execute MyHandler'
event_drive.event_list.append(MyHandler)
event_drive.run()
Protocols
Protocols描述瞭如何以異步的方式處理網絡中的事件。HTTP、DNS以及IMAP是應用層協議中的例子。Protocols實現了IProtocol接口,它包含如下的方法:
makeConnection 在transport對象和服務器之間建立一條連接 connectionMade 連接建立起來後調用 dataReceived 接收數據時調用 connectionLost 關閉連接時調用
Transports
Transports代表網絡中兩個通信結點之間的連接。Transports負責描述連接的細節,比如連接是面向流式的還是面向數據報的,流控以及可靠性。TCP、UDP和Unix套接字可作爲transports的例子。它們被設計爲“滿足最小功能單元,同時具有最大程度的可複用性”,而且從協議實現中分離出來,這讓許多協議可以採用相同類型的傳輸。Transports實現了ITransports接口,它包含如下的方法:
write 以非阻塞的方式按順序依次將數據寫到物理連接上 writeSequence 將一個字符串列表寫到物理連接上 loseConnection 將所有掛起的數據寫入,然後關閉連接 getPeer 取得連接中對端的地址信息 getHost 取得連接中本端的地址信息
將transports從協議中分離出來也使得對這兩個層次的測試變得更加簡單。可以通過簡單地寫入一個字符串來模擬傳輸,用這種方式來檢查。
例:EchoServer
from twisted.internet import protocol
from twisted.internet import reactor
class Echo(protocol.Protocol):
def dataReceived(self, data): # 只要twisted已收到數據就會把數據返回
self.transport.write(data)
def main():
factory = protocol.ServerFactory()
factory.protocol = Echo
reactor.listenTCP(1234,factory)
reactor.run()
if __name__ == '__main__':
main()
EchoClient
from twisted.internet import reactor, protocol
class EchoClient(protocol.Protocol):
"""Once connected, send a message, then print the result."""
def connectionMade(self): # 只要建立連接成功就會執行此方法
self.transport.write("hello alex!")
def dataReceived(self, data): # 只要收到數據就會調用此方法
"As soon as any data is received, write it back."
print("Server said:", data)
self.transport.loseConnection() # 如果數據未傳完則等數據傳輸完畢後再調用此方法connectionLost
def connectionLost(self, reason):
print("connection lost")
class EchoFactory(protocol.ClientFactory):
protocol = EchoClient
def clientConnectionFailed(self, connector, reason): # 如果連接不上就會調用此方法
print("Connection failed - goodbye!")
reactor.stop() # 連接失敗則關閉
def clientConnectionLost(self, connector, reason): # 如果連接過程中斷開則執行此方法
print("Connection lost - goodbye!")
reactor.stop() # 連接中斷關閉
# this connects the protocol to a server running on port 8000
def main():
f = EchoFactory()
reactor.connectTCP("localhost", 1234, f)
reactor.run()
# this only runs if the module was *not* imported
if __name__ == '__main__':
main()
運行服務器端腳本將啓動一個TCP服務器,監聽端口1234上的連接。服務器採用的是Echo協議,數據經TCP transport對象寫出。運行客戶端腳本將對服務器發起一個TCP連接,回顯服務器端的迴應然後終止連接並停止reactor事件循環。這裏的Factory用來對連接的雙方生成protocol對象實例。兩端的通信是異步的,connectTCP負責註冊回調函數到reactor事件循環中,當socket上有數據可讀時通知回調處理。