twisted框架学习
twisted为异步网络编程框架 twisted是一个具有强大功能且具有很强健壮性的库,其defer 异步 callback server application pb等抽象很好的解决了显示中的问题。 一:初步认识 #coding:utf-8 __author__ = 'zhoukunpeng' from twisted.internet import reactor def hello(): print "hello from the reactor loop!" reactor.callWhenRunning(hello) print "start the reactor" reactor.run() reactor.run()进入事件循环。 twisted默认的reactor是用select实现的,上面的这个等效于: from twisted.internet import selectreactor selectreactor.install() from twisted.internet import reactor def hello(): print "hello from the reactor loop!" reactor.callWhenRunning(hello) print "start the reactor" reactor.run() 修改twisted的默认线程池的大小: from twisted.internet import reactor reactor.suggestThreadPoolSize(20) 在twisted中还具有其他的reactor的实现,比较有名的一个就是poll实现的pollreactor。如果你要使用它,可以按照上面的方式进行。 twisted为单线程的。回调不仅仅是一个可选项,而是游戏规则的一部分,因此,我们应该确保回调函数不要浪费时间,要尽快返回。在回调函数中应该尽量避免阻塞I/O的函数。否则,会失去所有reactor所带来的优势。!! 当callback运行的时候reactor是停止的,callback应该尽可能的快! reactor.stop()用于停止事件循环,reactor stop以后再也无法run! twisted中如果出现了异常,服务是不会退出的!这就是网络服务器所应有的体格! 在twisted中一个良好的习惯就是,不是传递一个函数,而是传递一个实现了某些接口的对象。这样,可以一次传递多个callback. twisted提供给我们的多任务的处理方式是合作,twisted会告诉什么时候去读,什么时候去写,但是我们就要在尽可能处理多的数据情况下,又要防止拥塞,此外我们必须避免其他的堵塞的操作。 Twisted网络通信模型中最基本也要由三个部分组成:transports, protocols, factory, reactor 连接:代表了一个可以接受和发送数据的连接。 (仅提供了发送数据的方法,接受数据的方法未提供!为什么? 异步啊!)连接建立以后,这个对象也自动被reactor建立 协议:用来完成于一个已经连接成功的主机的交互功能,主要有数据的接受、发送、连接的断开事件也可以在这里处理 工厂:负责于一个协议启动和关闭功能,而且还负责在连接成功时生成一个协议对象。每个连接需要自己的协议,工厂的作用就是当一个连接进来的时候就已经为其准备好了协议。专业生产协议! 一个factory产生的协议均共享这个factory 反应器:用来执行时间循环,分发时间处理等。一个应用程序一般只启动一个reactor 一个典型的Twisted应用程序应该如下: ①. 建立一个协议类,可以从protocol.BaseProtocol类或其子类继承 ②. 建立一个工厂 ,可以从protocol.Factory或其子类继承。工厂至少应该制定protocol属性,指向协议类。通常把一些数据库读写的函数建立在工厂内。 ③. 启动事件循环,根据连接方向的不同可以选择reactor的connectXXX()或listenXXX()的方法。然后执行reactor.run()启动事件循环。 协议模型: 所有协议的基类是protocol.BaseProtocol其原型如下: class BaseProtocol: connected=0 transport=None def makeConnection(self,transport):不可重载 def connectionMade(self):#连接成功事件,可以重载 其可以看做为一个虚基类,实现功能比较简陋,实际应用中,一般不直接继承BaseProtocol而是继承Protoclo类! class Protocol(BaseProtocol): def dataReceived(self,data):接收到数据事件,可重载 pass def connectionLost(self,reason=connectionDone):连接断开事件,可重载,依靠reason区分断开类型 pass 从Protocol类继承就可以完成协议的基本处理了,包括连接的建立和断开事件,还有数据接受事件。 如果想要更加完整的协议功能,twisted.protocols包中寻找! 如果需要自己实现一种协议,比较推荐的是twisted.protocols.basic.LineReceiver类: LineReceiver默认按照文本行模型进行通信,接受数据也是以行为单位,也可以设置为以原始数据模式进行通信。 比较典型的应用就是HTTPChannel协议类,在头部请求/应答中使用行模式,在实体主体传输时,又是用的原始数据类型。 LineReceiver还是比较实用的。其类结构如下: class LineReceiver(protocol.Protoclo,_PauseableMixin): def clearLineBuffer(self):清空缓冲区 def setLineMode(self,extra=""):设置工作状态为行模式 def setRawMode(self):设置工作状态为原始数据模式 def rewDataReceived(self,data): 原始数据接受事件,可重载 def lineReceived(self,line): 行模式接受事件,可重载 def sendLine(self,line): 以行模式发送数据 发送原始数据可以通过self.transport实现,self.transport是所有的协议对象都拥有的成员,其方法大致如下: self.transport.write(data) 发送原始数据 self.transport.loseConnection() 关闭连接 self.transport.getPeer() 获取对方信息 self.transport.getHost() 获取本机消息。 工厂模型: 相对于协议,工厂可以发挥的控件就很小了,所有工厂的基类是twisted.internet.proctocol.Factory 这个类定义了三个方法。大致如下: class Factory: protocol=None #指向一个协议类。 def startFactory(self): 开启工厂,可以重载 def stopFactory(self): 关闭工厂,可以重载 def buildProtocol(self,addr): 构造协议对象,并给协议对象添加一个factory属性指向工厂,可以重载,但注意要再方法内继承原方法内容。 工厂还分为客户端工厂和服务器工厂。 服务器工厂: class SeverFactory(Factory): 客户端工厂: class ClientFactory(Factory): def startedConnecting(self,connecter): 连接建立成功时事件,可重载 def clientConnectionFailed(self,connector,reason):客户端连接失败,可重载 def clientConnectionLost(self,connector,reason):连接断开,可重载 此三个方法都传递了一个connector对象,这个对象有如下方法可以: connector.stopConnection()关闭对话 connector.connect() 一般在连接失败时,用于重新连接。 本例子中,主要用到了两个类,这两个类用于作为客户端进行工作。 ClientFactory:主要用于管理连接事件,创建Protocol对象,处理成功的连接。 Protocol:主要用于收发数据和决定是否关闭连接。 Protocol对象有一个属性叫做transport,代表当前活动的连接对象。 感悟: twisted也可以理解为三层的架构: reactor | factory | protocol reactor一般用connectXXX listenXXX等方法 factory 一定要设置protocol,一般用来控制连接的关闭和重连等。具有reactor操作权利 protocol 是协议的实现部分。 具有factory transport reactor操作权利。