首页 > 解决方案 > Mosquitto QoS2 错误 - 或微妙的规范解释?

问题描述

谁能解释为什么这个 MQTT QoS 消息永远不会被发送? 解答: 需要在 conf 文件中设置持久为真,然后会出现确切的预期行为。

在此处输入图像描述

更多详情

我有一个简单的问题(尽管有一个复杂的起始条件)。如果答案是“是”,那么 mosquitto 中存在一个错误,如果“否”,那么它是对我(我怀疑许多其他人)没有完全掌握的规范的非常微妙的解释。在第二种更可能的情况下,这意味着不可能在单个设备上使用 sub 和 pub 为同一主题编写完全符合 QoS2 的“序列测试器”。

订阅 T @ QoS2 并每次启动 clean==false 的设置代码。每 1 秒发布一个整数值增加的 T,这样在正常的操作过程中,事件的顺序是:

ETC

然后我故意以随机间隔断开与服务器的连接,以测试我的恢复程序。

重新启动时,我的测试客户端正确识别失败的 TX,因为它已存储状态,例如失败的 TX3 并重新发送,当然蚊子会重新确认......无论术语如何,如果中断位于 TX 4 路的中间,我的代码可以正确恢复,如果它位于 RX 4 路的中间,那么 mosquitto 会立即“恢复”它自己失败的 TX,并且一切都按预期进行。我从来没有得到任何 N 的“遗漏”值,我声明我的代码完全正常工作。那我的问题是什么?

连接中断/重新启动行为异常考虑何时 TX 和服务器 pub 之间的连接完全中断(我的下一个 RX 将是什么),即 TX3 完全成功 PUB/REC/REL/COMP,如果没有中断,我会打印“接收 3"。接下来我使用 mqtt-spy 发布 T[666]。然后我重新启动我的客户端。我得到的第一件事是来自服务器的 666 消息,这听起来对我来说是正确的,并且似乎同意:

当服务器获得传入应用程序消息的所有权时,它必须将其添加到那些具有匹配订阅的客户端的会话状态中。匹配规则在第 4.7 节 [MQTT-4.5.0-1] 中定义。和

[MQTT-3.1.2-4] | 如果 CleanSession 设置为 0,则服务器必须根据当前会话的状态(由客户端标识符标识)恢复与客户端的通信。如果没有与客户端标识符关联的会话,服务器必须创建一个新会话。Client 和 Server 必须在 Client 和 Server 断开连接后存储 Session。

但我再也见不到RX3了。

当然,同样的规则也适用于 TX3?服务器在发布我时获得了所有权,并且必须将其添加到我们当时共享的开放会话中,因此它知道我是尚未向其发送该消息的 QoS2 订阅者,方式与666,因此-根据我的逻辑-我必须接收重新发送的 RX3 以及 666?

除了 mosquitto 在未能重新发送 T[3] 时出错之外,唯一对我有意义的事情是对这个词的进一步解释:

[MQTT-3.1.2-5] | 在将 CleanSession 设置为 0 的会话断开连接后,服务器必须存储更多的 QoS 1 和 QoS 2 消息,这些消息与客户端在断开连接时所拥有的任何订阅相匹配,作为会话状态的一部分。

我看到 666 是如何“进一步”的,因为它发生在休息之后。我还看到 3 是在休息之前,因此不是“进一步”......所以你可以争辩说 moz 不应该被要求重新连接到同一个会话,但我仍然说如果 moz 没有兑现它对我的 QoS2 承诺,因为我曾经并且仍然是同一会话中该主题的订阅者,它知道它没有向我发送实例,无论它来自哪里!

如果这是正确的并且 moz 中没有错误,那么这意味着在物理上不可能在同一设备上编写具有 RX 和 TX 的背靠背 QoS2 测试程序......或者更准确地说是在同一个会话中。正如我的示例(以及我的许多wireshark 日志)最终证明消息3 永远不会在重新连接时发送。因此,我的测试人员“错过”了一个事务对并声称 QoS2 失败。具有讽刺意味的是,如果我将 TX 和 RX 放在两个单独的程序中,那么仅 RX(没有崩溃)肯定会收到它并保持“同步”并声称连续 QoS2 成功?我还没有对此进行测试,并会等着看我是否首先在这里得到一个有用的答案,以确保我没有遗漏任何东西(除了 RX[3] :))

但这似乎矛盾

服务器中的会话状态包括:

· 一个Session的存在,即使Session的其余状态为空。

· 客户的订阅。

· QoS 1 和 QoS 2 消息已发送到客户端,但尚未完全确认。

· QoS 1 和 QoS 2 消息等待传输到客户端。

· 已从客户端收到但尚未完全确认的 QoS 2 消息。

我看不出有什么理由说我丢失的 RX3 不是“等待传输到客户端的 QoS 1 和 QoS 2 消息”。无论是“进一步”还是其他!

最后,在同一点上,当 moz CONNACKs 设置会话时,这实际上意味着什么?我认为它的意思是它认为它有一些存储的会话需要重播,在这种情况下,我看到的下一件事应该是传入的 pubrels 等。当 session==true 但服务器没有发送任何内容时,这是什么意思?是告诉我它认为我应该有一些存储的会话数据需要重播吗?如果是这样,为什么?我已经知道了,因为 - 就像一个好孩子 - 我已经存储了会话状态,我在重新连接时会重播,所以我不需要被告知!对我来说, session==true 应该只意味着一件事:“等待一些传入的重播请求”......如果它再次出现,那么我看到 session==true 存在一个错误,并且在大多数情况下没有任何传入。如果不是,那么我又很困惑,我欣然承认这是最有可能的答案......但是:

在上面的例子中,mosquitto 是否应该在“脏会话”重新连接时发送 TX[3]?如果不是,为什么不呢?

标签: sessionmqttmosquitto

解决方案


解决方案是向 mosquitto.conf 文件添加持久真实


推荐阅读