python twisted - 在没有得到回复的已发送消息上超时

yok*_*oki 3 python client timeout twisted

我正在创建一种客户端 - 服务器实现,我想确保每个发送的消息都得到响应.所以我想创建一个超时机制,它不检查消息本身是否已传递,而是检查传递的消息是否得到响应.

IE,对于两台计算机1和2:

1: send successfully: "hello"
2: <<nothing>>
...
1: Didn't get a response for my "hello" --> timeout
Run Code Online (Sandbox Code Playgroud)

我想通过为每条消息创建一个带有id的大布尔数组来做这件事,该数组将保持"进行中"标志,并在收到消息的响应时设置.

我想知道也许有更好的方法.

谢谢,Ido.

det*_*tly 5

还有一种更好的方式,我自己刚刚在这里实施了.它使用TimeoutMixin来实现您需要的超时行为,并使用DeferredLock将正确的回复与发送的内容进行匹配.

from twisted.internet import defer
from twisted.protocols.policies import TimeoutMixin
from twisted.protocols.basic import LineOnlyReceiver

class PingPongProtocol(LineOnlyReceiver, TimeoutMixin):

    def __init__(self):
        self.lock = defer.DeferredLock()
        self.deferred = None

    def sendMessage(self, msg):
        result = self.lock.run(self._doSend, msg)
        return result

    def _doSend(self, msg):
        assert self.deferred is None, "Already waiting for reply!"

        self.deferred = defer.Deferred()
        self.deferred.addBoth(self._cleanup)
        self.setTimeout(self.DEFAULT_TIMEOUT)
        self.sendLine(msg)
        return self.deferred

    def _cleanup(self, res):
        self.deferred = None
        return res

    def lineReceived(self, line):
        if self.deferred:
            self.setTimeout(None)
            self.deferred.callback(line)
        # If not, we've timed out or this is a spurious line

    def timeoutConnection(self):
        self.deferred.errback(
            Timeout("Some informative message"))
Run Code Online (Sandbox Code Playgroud)

我没有测试过这个,它更像是一个起点.您可能需要在此处更改一些内容以满足您的目的:

  1. 我使用LineOnlyReceiver - 这与问题本身无关,您需要替换sendLine/ lineReceived使用适合您协议的API调用.

  2. 这是一个串行连接,所以我不处理connectionLost等你可能需要.

  3. 我喜欢直接在实例中保持状态.如果您需要额外的状态信息,请将其设置_doSend并清理干净_cleanup.有些人不喜欢这样 - 另一种方法是在_doSend关闭所需状态信息的内部创建嵌套函数.你仍然需要它self.deferred,否则lineReceived(或dataReceived)不知道该怎么做.

如何使用它

就像我说的,我为串行通信创建了这个,我不必担心工厂,connectTCP等.如果你正在使用TCP通信,你需要找出你需要的额外粘合剂.

# Create the protocol somehow. Maybe this actually happens in a factory,
# in which case, the factory could have wrapper methods for this.
protocol = PingPongProtocol()
def = protocol.sendMessage("Hi there!")
def.addCallbacks(gotHiResponse, noHiResponse)
Run Code Online (Sandbox Code Playgroud)