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实例,在不需要工厂时可以直接使用这个类来产生仅使用一次的客户端连接。这时,协议对象之间没有共享状态,也不需要重新连接。