Python Twisted:单独的协议处理

时间:2014-01-27 17:54:56

标签: python protocols twisted

我想在Twisted之上实现一个自己的基于TCP的协议,用于服务器。这种协议实现的机制是明确的(继承自Protocol并覆盖四个继承的方法,构建Factory)。

但是,我希望我的协议与应用程序逻辑分开,其方式如下:

  • 协议:从客户端接收数据,解码字节流并填充Python数据结构,获取数据结构,编码为字节流(基于文本)并响应客户端

  • 应用程序逻辑:接收所述数据结构,评估并返回响应数据结构

我如何以一种既不依赖于另一种方式(即松散耦合)的方式构建Twisted应用程序?我认为协议类将使用应用程序逻辑回调作为参数实例化?

修改

与此同时,我有这个:

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

class Logic:
    def process(self, data):
        return "Processed: %s" % data

class LineProtocol(Protocol):
    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)

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

你会认为这是“扭曲”的方式吗?有什么需要改进吗?

代码在LineFactory中创建一个Logic实例。好把它放在那里?

1 个答案:

答案 0 :(得分:3)

请注意,您的计划中已经有一个松耦合示例。处理TCP实现细节的传输与您的协议是分开的,两个对象通过一个定义明确的接口进行交互:dataReceived等等协议,write等有关传输的协议。

将这个想法延伸到另一个步骤。让您的应用程序对象和协议通过定义良好的接口进行交互。将应用程序对象作为__init__参数提供给协议是否与预期的交互有关。如果应用程序纯粹是被动的(即,它只是对协议上发生的事情作出反应,它本身不会启动事物)那么这是一个很好的方法。如果应用程序对驱动操作更感兴趣(例如,考虑驱动HTTP客户端协议的应用程序:在应用程序决定要发送请求之前,网络上什么都没有发生)那么您可能想要明确定义接口您的协议应该使用该应用程序(例如,HTTP客户端协议可能具有采用URL,HTTP方法等的request方法。)

请记住,有一些很好的API可以为您提供新的协议实例。例如:

from sys import argv

from twisted.internet.protocol import Protocol
from twisted.internet.endpoints import connectProtocol, clientFromString
from twisted.internet.task import react

def main(reactor, description):
    endpoint = clientFromString(reactor, description)
    connecting = connectProtocol(endpoint, Protocol())
    def connected(protocol):
        # Now `protocol` is connected somewhere and you can start
        # calling useful methods on it, if it has any.
        ...
    connecting.addCallback(connected)
    return connecting

react(main, argv[1:])

将一些有用的代码放入connected,将Protocol()替换为更有趣的协议类的实例,并使用an argument like“tcp:localhost:25”运行。

从你的例子:

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)

这不是真正有益的。您实际上没有在协议中实现任何协议逻辑。您所做的就是让self.factory._logic_callback负责实施协议。这是一些额外的对象,没有真正的好处。我不建议这样做。

您希望在协议类中执行所有解析和序列化。只将基于结构化对象(你所做的任何解析的输出)实现的高级逻辑委托给协议以外的其他东西。