【问题标题】:python twisted - Timeouting on a sent message that did not get a responsepython twisted - 在未得到响应的已发送消息上超时
【发布时间】:2011-07-05 14:33:49
【问题描述】:

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

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

1: send successfully: "hello"
2: <<nothing>>
...
1: Didn't get a response for my "hello" --> timeout

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

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

谢谢, 伊多。

【问题讨论】:

    标签: python timeout client twisted


    【解决方案1】:

    有一个更好的方法,有趣的是我自己just implemented here。它使用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"))
    

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

    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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-26
      • 2019-05-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多