由于缺乏更好的词汇,“交互式”客户端/服务器行为,我一直在努力思考如何让Twisted执行。
我设法将一对连接到服务的Protocol和ClientFactory类放在一起,并执行即时查询/响应(请参阅:connectionMade - > self.queryStatus)。这按预期成功,并从Factory类打印服务器的响应。
我现在的问题是,我将有外部事件必须导致数据被发送,同时总是侦听潜在的传入数据。但是一旦reactor.run()循环开始,我不确定我的应用程序的其余部分是如何触发数据发送的。
之后我尝试了一些不同的方法,但这是处理recv部分的最简单的方法:
class myListenerProtocol(LineReceiver):
delimiter = '\n'
def connectionMade(self):
print("Connected to: %s" % self.transport.getPeer())
self.queryStatus(1)
def dataReceived(self, data):
print("Receiving Data from %s" % self.transport.getPeer())
...
self.commandReceived(self.myData)
def commandReceived(self, myData):
self.factory.commandReceived(myData)
def connectionLost(self, reason):
print("Disconnected.")
def queryStatus(self, CommandValue):
...
strSend = CommandValue # or some such
self.transport.write(strSend)
class mySocketFactory(ClientFactory):
protocol = myListenerProtocol
def __init__(self):
pass
def buildProtocol(self, address):
proto = ClientFactory.buildProtocol(self, address)
return proto
def commandReceived(self, myData):
print myData
reactor.stop() # It won't normally stop after recv
def clientConnectionFailed(self, connector, reason):
print("Connection failed.")
reactor.stop()
def main():
f = mySocketFactory()
reactor.connectTCP("10.10.10.1", 1234, f)
reactor.run()
我认为这非常简单,但无数个小时的例子和文档都让我无法理解我是如何处理这种情况的。
答案 0 :(得分:1)
我现在的问题是,我的外部事件必须导致数据被发送,同时始终监听潜在的传入数据。但是一旦reactor.run()循环开始,我就不确定我的应用程序的其余部分是如何触发数据发送的。
"外部活动"?像什么?数据到达连接?很好,让反应堆运行意味着你实际上能够处理这些数据。
或许某人正在点击GUI中的按钮?尝试使用其中一个GUI集成反应堆 - 再次,在反应堆运行之前,您无法处理这些事件。
你可能会因为你认为你的主要功能应该reactor.run()
然后继续做其他事情而陷入困境。这不是它的工作原理。编写事件驱动程序时,您可以定义所有事件源,然后让事件循环在事件到达这些源时调用处理程序。
答案 1 :(得分:-1)
嗯,有很多方法,最好的方法实际上取决于你的应用程序的上下文,所以我不会在这里详细说明你这样做的一种方式,而是将你链接到我最近的一个阅读黑客的新闻:
和良好的用例示例,虽然它可能不适用于您正在处理的内容(或者您可能已阅读过):
顺便说一句,你也可以看看擅长处理这类事情的gevent或龙卷风。如果您的其他“事件”来自GUI工具包(如GTK或QT),请非常小心 GIL ,即使您只是想要命令行事件你需要线程并且仍然要小心。
最后,如果你想进行更多的交互,你也可以为你的服务器编写不同类型的“对等体”,它与你正在处理的不同用例交互(一个连接到GUI的客户端,另一个使用CLI,另一个使用数据库,另一个使用SAAS'API等。)。
换句话说,如果您的设计不起作用,请尝试改变您的观点!