我想在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实例。好把它放在那里?
答案 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
负责实施协议。这是一些额外的对象,没有真正的好处。我不建议这样做。
您希望在协议类中执行所有解析和序列化。只将基于结构化对象(你所做的任何解析的输出)实现的高级逻辑委托给协议以外的其他东西。