一、基本概念
Twisted 定義:
Twisted 是用 Python 實(shí)現(xiàn)的基于事件驅(qū)動的網(wǎng)絡(luò)引擎框架。具有以下特點(diǎn):
-- 可擴(kuò)展性高、基于事件驅(qū)動、跨平臺。
--Twisted 支持許多常見的傳輸及應(yīng)用層協(xié)議,如:TCP、UDP、SSL/TLS、HTTP、IMAP、SSH、IRC以及FTP。
--Twisted 對于其支持的所有協(xié)議都帶有客戶端和服務(wù)器的實(shí)現(xiàn)
二、Twisted架構(gòu)
設(shè)計(jì)哲學(xué)
Twisted 是一個事件驅(qū)動型的網(wǎng)絡(luò)引擎。事件驅(qū)動編程是一種編程范式,這里程序的執(zhí)行流由外部事件來決定。它的特點(diǎn)是包含一個事件循環(huán),當(dāng)外部事件發(fā)生時使用回調(diào)機(jī)制來觸發(fā)相應(yīng)的處理模型圖比較
單線程、多線程以及事件驅(qū)動編程模型的比較

注:其中灰色部分為每個任務(wù)阻塞在I/O操作上所花的 時間
從上圖可以看出:
單線程
在單線程同步模型中,任務(wù)按照順序執(zhí)行。如果某個任務(wù)因?yàn)?I/O 而阻塞,其他所有的任務(wù)都必須等待,直到它完成之后它們才能依次執(zhí)行。多線程
線程由操作系統(tǒng)來管理,在多處理器系統(tǒng)上可以并行處理,或者在單處理器系統(tǒng)上交錯執(zhí)行。這使得當(dāng)某個線程阻塞在某個資源的同時其他線程得以繼續(xù)執(zhí)行。但多線程程序難以推斷,如果實(shí)現(xiàn)不當(dāng)就會導(dǎo)致出現(xiàn)微妙且令人痛不欲生的 bug。事件驅(qū)動
多個任務(wù)交錯執(zhí)行,但仍然在一個單獨(dú)的線程中控制通過事件循環(huán)輪詢每個事件。不需要關(guān)心線程安全問題
三、實(shí)例呈現(xiàn)
(1)服務(wù)器的實(shí)現(xiàn)
Server.py
# coding=utf-8
from twisted.internet import reactor
from twisted.internet.protocol import Protocol, Factory
class SimpleProtocol(Protocol):
def connectionMade(self):
"""客戶端連入后向客戶端發(fā)送一條消息Hello"""
print 'success from ', self.transport.client
self.transport.write("Hello")
def connectionLost(self, reason):
print self.transport.client, 'disconnected'
print reason
def dataReceived(self, data):
print data
factory = Factory()
factory.protocol = SimpleProtocol
# 在9001端口進(jìn)行監(jiān)聽
reactor.listenTCP(9001, factory)
# 啟動事件循環(huán)
reactor.run()
其中SimpleProtocol是我復(fù)寫的一個Protocol.
(2)客戶端的實(shí)現(xiàn)
connection.py
# coding=utf-8
from twisted.internet.protocol import ClientFactory, Protocol
from twisted.internet import reactor
class Sender(Protocol):
def connectionMade(self):
"""連接成功后調(diào)用"""
self.send_command()
def send_command(self):
"""連接成功后調(diào)用他向服務(wù)端發(fā)送數(shù)據(jù)"""
self.transport.write("hello")
def dataReceived(self, data):
"""進(jìn)行數(shù)據(jù)的接受"""
print "DATA", data
class BasicClientFactory(ClientFactory):
def __init__(self, protocol):
self.protocol = protocol
def clientConnectionLost(self, connector, reason):
print 'Lost connection: %s' % reason.getErrorMessage()
PORT = 9001
HOST = '127.0.0.1'
# 實(shí)例化工廠對象
test = BasicClientFactory(Sender)
# 連接服務(wù)器
reactor.connectTCP(HOST, PORT, test)
reactor.run()
注:我復(fù)寫了客戶端所需要的工廠ClientFactory
(3)運(yùn)行測試
先在終端上運(yùn)行Server.py等待客戶端的連入,然后重新開一個終端運(yùn)行connection.py連接服務(wù)器。
會看到客戶端和服務(wù)端各自收到了一條來自對方的hello的問候消息(如下圖所示)。


四、代碼原理剖析
(1)
Factory:
每個服務(wù)器與客戶端都會有一個工廠。他負(fù)責(zé)創(chuàng)建連接。并創(chuàng)建 protocol 對象。Protocols:
Protocols 描述了如何以異步的方式處理網(wǎng)絡(luò)中的事件。當(dāng)連接創(chuàng)建成功后,F(xiàn)actory 會創(chuàng)建一個 protocol, 由 protocol 進(jìn)行通信。Transports
Transports 代表網(wǎng)絡(luò)中兩個通信結(jié)點(diǎn)之間的連接。Transports負(fù)責(zé)描述連接的細(xì)節(jié),
比如連接是面向流式的還是面向數(shù)據(jù)報的,流控以及可靠性。
(2)
-
Transports 實(shí)現(xiàn)了 ITransports 接口,它包含如下的方法:
-- write方法: 以非阻塞的方式按順序依次將數(shù)據(jù)寫到物理連接上。
-- writeSequence方法: 將一個字符串列表寫到物理連接上。
-- loseConnection 方法:將所有掛起的數(shù)據(jù)寫入,然后關(guān)閉連接。
-- getPeer方法: 取得連接中對端的地址信息。
-- getHost方法: 取得連接中本端的地址信息。 Protocols 實(shí)現(xiàn)了 IProtocol 接口,它包含如下的方法:
-- makeConnection方法: 在 transport 對象和服務(wù)器之間建立一條連接。
-- connectionMade方法: 連接建立起來后調(diào)用。
-- dataReceived方法: 接收數(shù)據(jù)時調(diào)用。
-- connectionLost方法: 關(guān)閉連接時調(diào)用。
(3)
- Reactor 模式:
Twisted 實(shí)現(xiàn)了設(shè)計(jì)模式中的反應(yīng)堆(reactor)模式,這種模式在單線程環(huán)境中調(diào)度多個事件源產(chǎn)生的事件到它們各自的事件處理例程中去。Twisted 的核心就是 reactor 事件循環(huán)。Reactor 可以感知網(wǎng)絡(luò)、文件系統(tǒng)以及定時器事件。它等待然后處理這些事件。
溫馨提示:
Twisted 沒有直接發(fā)送數(shù)據(jù)的函數(shù),發(fā)送數(shù)據(jù)通過Transports 中的 write 進(jìn)行數(shù)據(jù)的發(fā)送。