Xmpp ejabberd中流管理的奇怪错误

Xmpp ejabberd中流管理的奇怪错误,xmpp,ejabberd,stream-management,Xmpp,Ejabberd,Stream Management,我正在iOS上构建一个使用ejabberd的即时通讯应用程序。我目前正在测试流管理功能,尤其是在大多数情况下似乎都能正常工作的恢复功能。但是,有一种情况我不明白,我可以通过以下步骤进行复制,并考虑设置:恢复\u超时:30,在\u超时时重新发送\u:如果\u脱机 开始时,连接客户端A和客户端B,没有连接其他资源 客户端B以不干净的方式崩溃或断开连接 客户端A开始非常快地发送一组消息(10+) ejabberd为发送的每条消息向A发送一个ack,以确认消息到达服务器 碰撞发生后大约20秒,B重新连

我正在iOS上构建一个使用ejabberd的即时通讯应用程序。我目前正在测试流管理功能,尤其是在大多数情况下似乎都能正常工作的恢复功能。但是,有一种情况我不明白,我可以通过以下步骤进行复制,并考虑设置:恢复\u超时:30,在\u超时时重新发送\u:如果\u脱机

  • 开始时,连接客户端A和客户端B,没有连接其他资源
  • 客户端B以不干净的方式崩溃或断开连接
  • 客户端A开始非常快地发送一组消息(10+)
  • ejabberd为发送的每条消息向A发送一个ack,以确认消息到达服务器
  • 碰撞发生后大约20秒,B重新连接。此时,A收到之前发送的每条消息的错误

测试
我试过ejabberd 16.01

这种情况80%的时候都会发生;有时,A发送的消息在30秒内重新连接时会正确传递给B

我的问题是:

  • 这种行为正确吗?如果已经收到消息的ack,我希望不会将错误反弹到客户端A
  • 由于
    ressend\u on\u timeout
    设置为
    ,如果\u offline
    且没有连接其他资源,我希望不会出现任何错误。我说得对吗
      • 流管理确认仅表示您的服务器已收到消息。这并不意味着消息已被处理或传递到指定的地址。即使它被发送到了地址,那么该设备仍然可以为该节返回一个错误
      • 这实际上只是一个暗中操作,但在浏览了ejabberd代码之后,可能会发生以下情况:

      • clientB@mydomain/ResourceB
        断开连接,现在有一个会话正在等待使用
        ResourceB
        恢复
      • 客户端B重新连接,不恢复(因为它崩溃并失去状态)
      • 客户端B再次绑定资源
        ResourceB
      • 现在服务器必须终止等待恢复的休眠会话,因为客户端B请求了相同的资源
      • 服务器检查是否存在其他会话,因为它设置为“如果脱机”
      • 服务器看到有一个会话(新会话),因此选择跳出而不是重新发送
      • 所以我的理论是,
        if_offline
        只检查在需要处理未确认消息队列时是否有其他会话,而不是在最初接收消息时


      @xnyhps的回答是正确的,我将在下一个ejabberd版本中介绍这个特殊的案例。然而,@xnyhps也正确地指出,还有其他一些极端情况,因此如果您想要可靠的消息传递,应该使用XEP-0313。XEP-0198的主要功能是会话恢复。

      这绝对有道理。在这种特殊情况下,ejabberd是否需要检查资源并重新发送消息,而不是将错误发送给发送者?@theMoonlitKnight XEP-0198有许多边缘情况,消息可能会丢失。如果要确保获得所有消息,应使用XEP-0313将消息存储在服务器上,然后检索它们。