gpt4 book ai didi

当客户端连接突然丢失时,xmpp 消息丢失

转载 作者:行者123 更新时间:2023-12-04 22:43:22 25 4
gpt4 key购买 nike

我正在使用 ejabberd 服务器和 ios xmppframework。
有两个客户,A 和 B。

  1. When A and B are online, A can send message to B successfully.
  2. If B is offline, B can receive the message when B is online again.
  3. But when B is suddenly/unexpectedly lost connection, such as manually close wi-fi, the message sent by A is lost. B will never receive this message.


我猜原因是B突然失去连接,服务器仍然认为B在线。因此,离线消息在这种情况下确实有效。

所以我的问题是如何确保A发送的消息会被B接收?确保没有消息丢失。

最佳答案

上周我一直在尝试在我的 XMPPFramework 和 eJabberd 消息传递应用程序中追踪丢失的消息。以下是我为保证消息传递而经历的完整步骤以及每个步骤的效果。

模组离线

在 ejabberd.yml 配置文件中确保你在访问规则中有这个:

max_user_offline_messages:
admin: 5000
all: 100

这在模块部分:
mod_offline:
access_max_user_messages: max_user_offline_messages

当服务器知道消息的接收者离线时,他们将存储它并在重新连接时传递它。

平 (XEP-199)
xmppPing = XMPPPing()
xmppPing.respondsToQueries = true
xmppPing.activate(xmppStream)

xmppAutoPing = XMPPAutoPing()
xmppAutoPing.pingInterval = 2 * 60
xmppAutoPing.pingTimeout = 10.0
xmppAutoPing.activate(xmppStream)

Ping 就像心跳一样,因此服务器知道用户何时离线但没有正常断开连接。最好不要依赖 applicationDidEnterBackground 上的断开连接。但是当客户端失去连接或流由于未知原因断开连接时,有一段时间客户端离线但服务器还不知道它,因为直到将来某个时候才会预期 ping。在这种情况下,邮件不会传递,也不会存储以供离线传递。

流管理 (XEP-198)
xmppStreamManagement = XMPPStreamManagement(storage: XMPPStreamManagementMemoryStorage(), dispatchQueue: dispatch_get_main_queue())
xmppStreamManagement.autoResume = true
xmppStreamManagement.addDelegate(self, delegateQueue: dispatch_get_main_queue())
xmppStreamManagement.activate(xmppStream)

然后在 xmppStreamDidAuthenticate
xmppStreamManagement.enableStreamManagementWithResumption(true, maxTimeout: 100)

就快到了。最后一步是返回 ejabberd.yml并将这一行添加到 access: c2s 下面的监听端口部分:
resend_on_timeout: true

流管理在每次消息传递后添加 req/akn 握手。它本身不会对服务器端产生任何影响,除非 resend_on_timeout已设置(在 eJabberd 上不是默认设置)。

当接收到的消息的确认没有到达服务器并决定保留它以供离线传递时,需要考虑最后一个边缘情况。下次客户端登录时,他们可能会收到重复的消息。为了处理这个问题,我们为 XMPPStreamManager 设置了该委托(delegate)。实现 xmppStreamManagement getIsHandled:如果消息有聊天正文,则设置 isHandledPtr为假。当您构造出站消息时,添加一个具有唯一 id 的 xmppElement:
let xmppMessage = XMPPMessage(type: "chat", to: partnerJID)
let xmppElement = DDXMLElement(name: "message")
xmppElement.addAttributeWithName("id", stringValue: xmppStream.generateUUID())
xmppElement.addAttributeWithName("type", stringValue: "chat")
xmppElement.addAttributeWithName("to", stringValue: partnerJID.bare())
xmppMessage.addBody(message)
xmppMessage.addChild(xmppElement)
xmppMessage.addReceiptRequest()
xmppStream.sendElement(xmppMessage)

然后当你收到消息时,通知流管理器该消息已被 xmppStreamManager.markHandledStanzaId(message.from().resource) 处理。

这最后一步的目的是建立一个唯一标识符,您可以将其添加到 XMPPMessageArchivingCoreDataStorage并在显示前检查重复项。

关于当客户端连接突然丢失时,xmpp 消息丢失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30623833/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com