python twins - 发送消息超时但未得到响应

发布于 2024-10-19 16:02:12 字数 371 浏览 3 评论 0 原文

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

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

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

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

我想知道也许有更好的方法可以做到这一点。

谢谢, 我愿意。

I am creating a sort of a client-server implementation, and I'd like to make sure that every sent message gets a response. So I want to create a timeout mechanism, which doesn't check if the message itself is delivered, but rather checks if the delivered message gets a response.

IE, for two computers 1 and 2:

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

I thought of doing it by creating a big boolean array with id for each message, which will hold a "in progress" flag, and will be set when the message's response is received.

I was wondering perhaps there was a better way of doing that.

Thanks,
Ido.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

绳情 2024-10-26 16:02:12

有一个更好的方法,有趣的是我自己刚刚在这里实现< /a>.它使用 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)

There is a better way, which funnily enough I myself just implemented here. It uses the TimeoutMixin to achieve the timeout behaviour you need, and a DeferredLock to match up the correct replies with what was sent.

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"))

I haven't tested this, it's more of a starting point. There are a few things you might want to change here to suit your purposes:

  1. I use a LineOnlyReceiver — that's not relevant to the problem itself, and you'll need to replace sendLine/lineReceived with the appropriate API calls for your protocol.

  2. This is for a serial connection, so I don't deal with connectionLost etc. You might need to.

  3. I like to keep state directly in the instance. If you need extra state information, set it up in _doSend and clean it up in _cleanup. Some people don't like that — the alternative is to create nested functions inside _doSend that close over the state information that you need. You'll still need that self.deferred there though, otherwise lineReceived (or dataReceived) has no idea what to do.

How to use it

Like I said, I created this for serial communications, where I don't have to worry about factories, connectTCP, etc. If you're using TCP communications, you'll need to figure out the extra glue you need.

# 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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文