上周我一直在尝试在我的 XMPPFramework 和 eJabberd 消息传递应用程序中查找丢失的消息。以下是我为保证消息传递而执行的完整步骤以及每个步骤的效果。
Mod_offline
在 ejabberd.yml 配置文件中确保你在访问规则中有这个:
max_user_offline_messages:
admin: 5000
all: 100
这在模块部分:
mod_offline:
access_max_user_messages: max_user_offline_messages
当服务器知道消息的接收者离线时,它们将存储它并在重新连接时传递它。
Ping (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 设置了该委托。实现xmppStreamManagement getIsHandled:,如果消息有聊天正文,则将isHandledPtr 设置为false。当您构造出站消息时,添加一个具有唯一 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 并在显示之前检查重复项。