什么是Twisted:
twisted是一个用python语言写的事件驱动的网络框架,支持很多种协议。
什么是事件驱动编程:
事件驱动编程是一种编程范式,这里程序的执行流由外部事件来决定。它的特点是包含一个事件循环,当外部事件发生时使用回调机制来触发相应的处理。在事件驱动程序中,多个任务交错执行,但是仍然在一个单独的线程控制中。当处理I/O等昂贵的操作时,注册一个回调到事件循环中,当I/O操作完成时继续执行。好处:程序员不需要考虑多线程环境下的共享数据被同时操作的安全问题。
以下几种情况,可以选用事件驱动编程:
1.程序中有很多任务,且任务之间高度独立,等待事件到来时,某些任务会被阻塞;
2.当应用程序需要在任务间共享可变的数据时,因为这里不需要采用同步处理。
Twisted中的几个基本元素:
1.Application:一个应用程序中包含多个Service
2.Service:服务负责启动端口
3.协议工厂(Factory):用于生产协议对象
4.协议(Protocol):每一个协议对应一个网络连接;
Twisted实现了设计模式中的反应堆(reactor)模式:
Reactor是一种广泛应用在服务器端开发的设计模式。对于应用服务器,一个主要规律就是,CPU的处理速度是要远远快于IO速度的,如果CPU为了IO操作(例如从Socket读取一段数据)而阻塞显然是不划算的。好一点的方法是分为多进程或者线程去进行处理,但是这样会带来一些进程切换的开销,试想一个进程一个数据读了500ms,期间进程切换到它3次,但是CPU却什么都不能干,就这么切换走了,是不是也不划算?这时先驱们找到了事件驱动,或者叫回调的方式,来完成这件事情。这种方式就是,应用业务向一个中间人注册一个回调(event handler),当IO就绪后,就这个中间人产生一个事件,并通知此handler进行处理。
Deferred对象:
在异步版中需要由程序员自己负责正确调用成功和失败情况下的回调链。如果由于编程错误,reactor事件循环将永远不会停止,程序就会卡住。为此,twisted应对这种复杂性的方式是新增一个称为Deferred(延迟)的对象。
Transports:
Transports代表网络中两个通信结点之间的连接。Transports负责描述连接的细节,比如连接是面向流式的还是面向数据报的,流控以及可靠性。
Transports实现了ITransports接口,它包含如下的方法:
write 以非阻塞的方式按顺序依次将数据写到物理连接上writeSequence 将一个字符串列表写到物理连接上loseConnection 将所有挂起的数据写入,然后关闭连接getPeer 取得连接中对端的地址信息getHost 取得连接中本端的地址信息
Protocols:
Protocols描述了如何以异步的方式处理网络中的事件。HTTP、DNS以及IMAP是应用层协议中的例子。Protocols实现了IProtocol接口,它包含如下的方法:
makeConnection 在transport对象和服务器之间建立一条连接connectionMade 连接建立起来后调用dataReceived 接收数据时调用connectionLost 关闭连接时调用
以一个例子来说明reactor、protocols以及transports这三者之间的关系。以下是完整的echo服务器和客户端的实现:
server.py
from twisted.internet import protocol, reactor
class Echo(protocol.Protocol):
def dataReceived(self, data):
self.transport.write(data)
class EchoFactory(protocol.Factory):
def buildProtocol(self, addr):
return Echo()
reactor.listenTCP(8000, EchoFactory())
reactor.run()
client.py
from twisted.internet import reactor, protocol
class EchoClient(protocol.Protocol):
def connectionMade(self):
self.transport.write("hello, world!")
def dataReceived(self, data):
print "Server said:", data
self.transport.loseConnection()
def connectionLost(self, reason):
print "connection lost"
class EchoFactory(protocol.ClientFactory):
def buildProtocol(self, addr):
return EchoClient()
def clientConnectionFailed(self, connector, reason):
print "Connection failed - goodbye!"
reactor.stop()
def clientConnectionLost(self, connector, reason):
print "Connection lost - goodbye!"
reactor.stop()
reactor.connectTCP("localhost", 8000, EchoFactory())
reactor.run()
TAC文件
[size=14.4444446563721px]当在一个普通的Python文件中管理Twisted应用程序时,需要由开发者负责编写启动和停止reactor事件循环以及配置应用程序的代码。在Twisted的基础组件中,协议的实现都是在一个模块中完成的,需要使用到这些协议的Service可以注册到一个Twisted应用程序配置文件中(TAC文件)去,这样reactor事件循环和程序配置就可以由外部组件来进行管理。
[size=14.4444446563721px]要将我们的Echo服务器转变成一个Echo应用,我们可以按照以下几个简单的步骤来完成:
将Echo服务器的Protocol部分移到它们自己所归属的模块中去。
在TAC文件中:
创建一个Echo应用。
创建一个TCPServer的Service实例,它将使用我们的EchoFactory,然后同前面创建的应用完成注册。
创建一个 echo.tac 文件
#!/usr/bin/env python
# coding: utf-8
from twisted.application import service, internet
from echoServ import EchoFactory
# 创建应用程序对象
application = service.Application('Echo 服务程序')
# 创建 service 对象
myServices = internet.TCPServer(8007, EchoFactory())
# 设置 application 为 service 的父元素
myservices.setServiceParent(application)
用守护进程方式运行服务
twistd -y echo.tac
部分内容引用自:
http://f.dataguru.cn/forum.php?mod=viewthread&tid=373703