Twisted中不同协议如何相互作用
我想要让两种不同的协议相互作用,场景如下:
A和B是两种不同的协议。
首先,A会和服务器进行交互,获取一些值。
只有在A完成获取这些值后,B才会开始和服务器进行交互。
现在我的问题是,是否有一种优雅的方法来初始化B,当A获取到值的时候。
目前我只是把B的初始化放在A的数据处理函数里。但我觉得这样并不优雅。
我所说的优雅的方法是,B的初始化应该由一个流程控制器或者类似的东西来完成,而不是由另一个协议来完成。
有没有什么优雅的方法呢?比如使用defered或者其他的东西。
我刚接触twisted,对defered还不是很了解……
非常感谢!
1 个回答
1
听起来你已经迈过了第一个难关——搞清楚怎么让A和B之间有互动。这很好,因为对大多数人来说,这个概念上的挑战是最大的。至于怎么让它看起来更“优雅”,如果你想要一种方法,把协议代码和驱动它的应用代码(也就是“业务逻辑”)分开,有几种选择。我会给你一个基于Deferreds的例子。
我们来考虑两个POP3客户端。你希望第一个客户端获取消息列表,然后第二个客户端从这个列表中获取第一条消息。这个例子
from twisted.internet import defer, protocol, reactor
from twisted.mail.pop3 import AdvancedPOP3Client
class MessageDownloader(object):
def __init__(self, host, port, user, password):
self.host = host
self.port = port
self.user = user
self.password = password
self.cc = ClientCreator(reactor, AdvancedPOP3Client)
def connect(self):
"""
Connect to the POP3 server and authenticate. Return a Deferred
which fires with the connected protocol instance.
"""
connDeferred = self.cc.connect(self.host, self.port)
def cbAuthenticate(proto):
loginDeferred = proto.login(user, password)
loginDeferred.addCallback(lambda ignored: proto)
return loginDeferred
connDeferred.addCallback(cbAuthenticate)
return connDeferred
def run(self):
connDeferred = self.connect()
connDeferred.addCallback(self.cbFirstConnection)
return connDeferred
def cbFirstConnection(self, firstProto):
listDeferred = firstProto.listUID()
def cbListed(uidList):
connDeferred = self.connect()
def cbConnected(secondProto):
return secondProto.retrieve(uidList[0])
connDeferred.addCallback(cbConnected)
listDeferred.addCallback(cbListed)
return listDeferred
if __name__ == '__main__':
import sys
MessageDownloader(*sys.argv[1:]).run()
reactor.run()
在这里,获取UID列表和建立新连接以获取消息的所有逻辑都和实际的协议实现分开了(这些实现完全在Twisted中)。几乎所有使用的API返回的Deferreds允许你的应用程序以任何想要的方式连接事件。