2014-01-27 47 views
3

我想实现一个自己的基于TCP的协议,用于Twisted之上的服务器。这种协议实现的机制很明确(继承协议并覆盖四个继承的方法,建立Factory)。Python扭曲:从处理中分离协议

但是,我想我的协议为从应用逻辑分离的,在一种方式:

  • 协议:从客户端接收数据时,字节流进行解码,并填充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实例。很好把它放在那里?

+0

到目前为止你有什么? – SingleNegationElimination

+0

“进程”是任何语言中使用任何库的方法最糟糕的名称之一。 –

+0

@ Jean-PaulCalderone:同意,请原谅我在这个示例中使用它。 – Bernd

回答

3

请注意,您的计划中已经有一个松耦合的例子。处理TCP实现细节的传输与协议是分开的,两个对象通过一个定义良好的接口进行交互:dataReceived et al on protocol,write et al on the transport。

只是将此想法延伸到另一个步骤。让你的应用程序对象和协议通过一个定义良好的接口进行交互。应用程序对象是否作为__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:本地主机: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负责实施协议。这是一对额外的物体,没有真正的好处。我不会建议这样做。

你想在协议类中做所有的解析和序列化。只能委托更高级别的逻辑,用结构化对象(任何解析的输出)来实现,而不是协议。