Python Twisted: 将协议与处理逻辑分离

85 阅读3分钟

在 Twisted 框架中,我们需要实现一个基于 TCP 的协议,该协议将在服务器端使用。在此过程中,协议的实现机制是明确的(继承自 Protocol 并覆写四个继承的方法,构建 Factory)。但我们希望协议与应用程序逻辑是分离的,这样可以实现:

huake2_00020_.png 协议:接收来自客户端的数据,解码字节流并填充 Python 数据结构,获取数据结构,编码为字节流(基于文本)并响应客户端。 应用程序逻辑:接收上述数据结构,评估并返回响应数据结构。

我们希望构建一个 Twisted 应用程序,以满足以上需求,且协议和应用程序逻辑彼此独立(即松散耦合)。我们可以想象,协议类将以应用程序逻辑回调作为参数实例化。

2、解决方案

为了实现协议与处理逻辑的分离,有一种常用的方法是通过接口进行通信。协议和应用程序逻辑之间通过一个定义明确的接口进行交互,这样就可以将它们解耦。例如,我们可以创建一个 Protocol 接口,定义了协议需要实现的方法,例如 dataReceived、connectionMade 等。然后,应用程序逻辑可以实现这个接口,并将其作为参数传递给协议类。这样,协议类就可以通过接口与应用程序逻辑进行通信,而无需直接依赖应用程序逻辑的具体实现。

以下是使用接口来实现协议与处理逻辑分离的代码示例:

from twisted.internet.protocol import Protocol
from twisted.internet.protocol import Factory
from twisted.internet.endpoints import TCP4ServerEndpoint
from twisted.internet import reactor


# 定义协议接口
class IProtocol:
    def dataReceived(self, data):
        pass

    def connectionMade(self):
        pass

    def connectionLost(self, reason):
        pass


# 实现协议接口
class LineProtocol(Protocol):
    implements(IProtocol)

    def dataReceived(self, data):
        print("Received: %s" % data)
        if self.factory._logic_callback:
            # 调用应用程序逻辑的回调函数处理数据
            ret = self.factory._logic_callback.process(data)
            print("Sent: %s" % ret)
            self.transport.write(ret)

    def connectionMade(self):
        print("Connection made.")

    def connectionLost(self, reason):
        print("Connection lost.")


# 应用程序逻辑
class Logic:
    def process(self, data):
        return "Processed: %s" % data


# 工厂类
class LineFactory(Factory):
    protocol = LineProtocol

    def __init__(self, logic_callback=None):
        if logic_callback:
            self._logic_callback = logic_callback()
        else:
            self._logic_callback = None


# 创建端点并监听
endpoint = TCP4ServerEndpoint(reactor, 1234)
endpoint.listen(LineFactory(Logic))
reactor.run()

在上面的代码中,我们定义了一个 IProtocol 接口,并实现了一个 LineProtocol 协议类来实现该接口。应用程序逻辑通过 Logic 类来实现,并将其作为参数传递给 LineFactory。这样,LineProtocol 就可以通过 IProtocol 接口与 Logic 进行通信,而无需直接依赖 Logic 的具体实现。

这种方法的好处是,协议和应用程序逻辑是松散耦合的,可以很容易地进行修改和扩展。例如,如果我们需要改变应用程序逻辑,我们可以简单地创建一个新的 Logic 类,而无需修改协议类。同样,如果我们需要改变协议,我们也可以简单地创建一个新的 LineProtocol 类,而无需修改应用程序逻辑。