在Twisted上有一天的经验,我试着安排回复tcp客户端的消息发送:
import os, sys, time
from twisted.internet import protocol, reactor
self.scenario = [(1, "Message after 1 sec!"), (4, "This after 4 secs"), (2, "End final after 2 secs")]
for timeout, data in self.scenario:
reactor.callLater(timeout, self.sendata, data)
print "waited %d time, sent %s\n"%(timeout, data)
现在它发送消息,但我有两个问题:
1) “timeout”从“now”开始,我想在前一个任务完成(前一条消息已发送)后计算它
2) 我不知道如何在所有邮件发送后关闭连接。如果我把self.transport.loseConnection()
放在callLater
之后,它会立即关闭连接。
在之前的尝试中,我没有使用reactor.callLater
,而是只在for
循环中使用self.transport.write()
和time.sleep(n)
。在这种情况下,所有消息都是在所有超时之后一起发送的。。。不是我想要的。
目的是等待客户端连接、等待超时1和发送消息1、等待超时2和发送消息2。。。等最后一条消息后-关闭连接。
这笔交易的最终解决方案。。
在使用Twisted时,需要认识到的重要一点是,没有什么可以等待任何东西。当你调用
reactor.callLater()
时,你要求反应器稍后调用一些东西,而不是现在。调用立即结束(在调度了调用之后,在执行它之前)。因此,您的print
语句是一个谎言:您没有等待timeout
时间;您根本没有等待。你可以用多种方法修复它,使用哪种取决于你真正想要什么。如果希望第二个任务在第一个任务启动4秒后启动,只需将第一个任务的延迟(您的
timeout
变量)添加到第二个任务的延迟中。不过,第一个任务可能不会在您计划的时间准确开始;如果Twisted太忙而不能更早开始,它可能会在稍后开始。另外,如果你的任务需要很长时间,在第二个任务开始之前,它可能不会真正完成。更常见的方法是第一个任务调度第二个任务,而不是立即调度第二个任务。您可以在第一个任务结束后4秒(通过在第一个任务结束时调用
reactor.callLater()
)或在第一个任务开始后4秒(通过在第一个任务的start处调用reactor.callLater()
)安排它,也可以执行更复杂的计算来确定它应该何时开始,并跟踪已用时间。当您在Twisted等待中什么都没有意识到时,在执行完所有计划任务后关闭连接就变得很容易了:您只需要调用最后一个任务
self.transport.loseConnection()
。对于更复杂的情况,您可能希望将Deferred
链接在一起,或者使用DeferredList
在所有挂起任务都已完成时执行loseConnection()
,即使它们不是严格顺序的。相关问题 更多 >
编程相关推荐