不同协议如何在 Twisted 中相互交互

发布于 2024-09-02 10:46:48 字数 314 浏览 7 评论 0原文

我希望两个不同的协议相互交互的场景如下:

A和B是两个不同的协议。 首先 A 将与服务器交互并检索一些值。 只有当 A 完成检索值后,B 才会开始与服务器交互。

现在我的问题是,当 A 检索值时,是否有一种优雅的方式来初始化 B 。

目前我只是在A的数据处理函数中以B开头。但我不认为这是一种优雅的方式。

我的意思是,一种优雅的方式是 B 的初始化是由流量控制器或类似的东西完成的,而不是其他协议。

有优雅的方法吗?这样使用延迟或任何其他东西。

我只是扭曲的新手,不太了解延迟......

非常感谢!

The scenario I want two different protocols interact with each other is as below:

A and B is two different protocols.
First A will interact with the server and retrieve some values.
Only after A finishes retrieving the values , B will start to interact with the server.

Now my problem is that is there an elegant way to initial B when A retrieves the values.

Currently I just initial B in A's data process function. But i don't think that this is an elegant way.

What I mean an elegant way is that the initialization of B is done by a flow controller or something like that, but not another protocol.

Is there an elegant way? such using defered or any other things.

I'm just new to twisted, not knowing very much about defered....

Thank you very much!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

谢绝鈎搭 2024-09-09 10:46:48

听起来您已经跨过了第一个障碍 - 弄清楚如何让 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 允许事件按照您的应用程序的需要进行连接。

It sounds like you've gotten past the first hurdle - figuring out how to have A and B interact at all. That's good, since for most people that's the biggest conceptual challenge. As for making it elegant, if you're after an approach that keeps your protocol code isolated from the application code driving it (ie, the "business logic"), there are several options. I'll give an example of one based on Deferreds.

Let's consider two POP3 clients. You want the first to retrieve a message list, then the second to retrieve the first message from the resulting list. This example

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()

Here, all of the logic about retrieving a list of UIDs and setting up a new connection to retrieve a message is separate from the actual protocol implementation (which is entirely in Twisted). The Deferreds returned from almost all of the APIs used here allow events to be connected up however your application wants.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文