Twisted:如何在初始连接时识别协议,然后委托给适当的协议实现?

2024-03-28 21:36:19 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在编写一个Python程序,它将使用Twisted连接到TCP服务器。套接字另一端的服务器可能正在运行两种可能的协议之一(protoA或protoB),但在我启动连接并“询问”服务器正在使用哪种协议之前,我不知道是哪一种。一旦连接好,我就可以确定使用的是协议的哪个版本(protoA还是protoB),但我并不提前知道。在

显然,一个解决方案是在我的twisted Protocol派生类中有很多特殊情况的代码——也就是说,如果protoA这样做,elif protoB会做其他的事情。但是,我希望能够将两个独立协议的代码保存在两个独立的协议实现中(尽管它们可能通过基类共享一些功能)。由于协议的两个版本都涉及到维护状态,因此必须将两个版本混入同一个类中可能会很快混淆。在

我该怎么做?是否有一种方法可以在工厂实现中执行最初的“协议标识”步骤,然后实例化正确的协议派生?在


Tags: 代码程序版本服务器协议twisted情况解决方案
2条回答

不要在整个协议实现中混合决策逻辑,而是将其放在一个地方。在

class DecisionProtocol(Protocol):
    def connectionMade(self):
        self.state = "undecided"

    def makeProgressTowardsDecision(self, bytes):
        # Do some stuff, eventually return ProtoA() or ProtoB()

    def dataReceived(self, bytes):
        if self.state == "undecided":
            proto, extra = self.makeProgressTowardsDecision(bytes)
            if proto is not None:
                self.state = "decided"
                self.decidedOnProtocol = proto
                self.decidedOnProtocol.makeConnection(self.transport)
                if extra:
                    self.decidedOnProtocol.dataReceived(extra)

        else:
            self.decidedOnProtocol.dataReceived(bytes)

    def connectionLost(self, reason):
        if self.state == "decided":
            self.decidedOnProtocol.connectionLost(reason)

最终,您可能可以用更少的样板文件来实现这一点:http://tm.tl/3204/

这是很容易做到的一些魔术。在

class MagicProtocol(Protocol):
    ...
    def dataReceived(self, data):
        protocol = self.decideProtocol(data)
        for attr in dir(protocol):
            setattr(self, attr, getattr(protocol, attr))

这很难看,但它会有效地为choosen协议切换魔术协议。在

相关问题 更多 >