【问题标题】:XMPP messages lost on Android while switching data connectivity (e.g. turning Wifi of, GSM <-> Wifi switch)切换数据连接时在 Android 上丢失 XMPP 消息(例如,关闭 Wifi,GSM <-> Wifi 开关)
【发布时间】:2014-08-31 17:13:19
【问题描述】:

我正在用 android 开发一个聊天应用程序。使用 XMPP 服务器。 PHP 服务器已迁移到 ejabber。

我的通知在所有情况下都能正常工作。但在一种情况下,我丢失了 XMPP 消息。事实上,我没有收到通知。

具体来说,我正在关闭 WiFi 或数据连接。在关闭 WiFi 或数据连接后,发送给我的任何通知都没有收到。当我打开 WiFi 或数据连接后,我无法收到发送给我的消息。

我已经在后台实现了服务。这使得 xmpp 连接始终有效。

我在关闭 WiFi 连接时收到此错误。

java.net.SocketException: sendto failed: EPIPE (Broken pipe)
java.net.SocketException: recvfrom failed: ETIMEDOUT (Connection timed out)
   at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:506)
   at libcore.io.IoBridge.sendto(IoBridge.java:475)
   at java.net.PlainSocketImpl.write(PlainSocketImpl.java:508)
   at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:46)
   at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:270)
   at java.io.OutputStreamWriter.flushBytes(OutputStreamWriter.java:167)
   at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:158)
   at java.io.BufferedWriter.flush(BufferedWriter.java:124)
   at org.jivesoftware.smack.PacketWriter.writePackets(PacketWriter.java:286)
   at org.jivesoftware.smack.PacketWriter.access$12(PacketWriter.java:270)
   at org.jivesoftware.smack.PacketWriter$1.run(PacketWriter.java:137)
Caused by: libcore.io.ErrnoException: sendto failed: EPIPE (Broken pipe)
   at libcore.io.Posix.sendtoBytes(Native Method)
   at libcore.io.Posix.sendto(Posix.java:146)
   at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:177)
   at libcore.io.IoBridge.sendto(IoBridge.java:473)
   ... 9 more
   at libcore.io.IoBridge.maybeThrowAfterRecvfrom(IoBridge.java:552)
   at libcore.io.IoBridge.recvfrom(IoBridge.java:516)
   at java.net.PlainSocketImpl.read(PlainSocketImpl.java:489)
   at java.net.PlainSocketImpl.access$000(PlainSocketImpl.java:46)
   at java.net.PlainSocketImpl$PlainSocketInputStream.read(PlainSocketImpl.java:241)
   at java.io.InputStreamReader.read(InputStreamReader.java:244)
   at java.io.BufferedReader.read(BufferedReader.java:310)
   at org.jivesoftware.smack.XMPPConnection$AliveReader.read(XMPPConnection.java:1122)
   at org.kxml2.io.KXmlParser.fillBuffer(KXmlParser.java:1496)
   at org.kxml2.io.KXmlParser.peekType(KXmlParser.java:979)
   at org.kxml2.io.KXmlParser.next(KXmlParser.java:346)
   at org.kxml2.io.KXmlParser.next(KXmlParser.java:310)
   at org.jivesoftware.smack.PacketReader.parsePackets(PacketReader.java:321)
   at org.jivesoftware.smack.PacketReader.access$1(PacketReader.java:216)
   at org.jivesoftware.smack.PacketReader$1.run(PacketReader.java:70)
Caused by: libcore.io.ErrnoException: recvfrom failed: ETIMEDOUT (Connection timed out)
   at libcore.io.Posix.recvfromBytes(Native Method)
   at libcore.io.Posix.recvfrom(Posix.java:131)
   at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
   at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
   ... 13 more

【问题讨论】:

  • 我在 android 中遇到了同样的问题,但我们有 OPENFIRE XMPP 服务器...您能提供任何想法吗?
  • 嗨 @mark 我会向您发送有关 OPENFIRE 配置的邮件,请您将电子邮件 ID 发送给我
  • deep@hyperlinkinfosystem.com

标签: android xmpp smack asmack


【解决方案1】:

所以要安装 mod_archive,我需要这样做,典型的: 在cmd中写入以下行。 (对于分操作系统)

以 root 身份登录 创建新目录:

mkdir ejabberd_archive_plugin
cd ejabberd_archive_plugin

现在使用以下命令获取最新的 ejabberd 模块

yum https://svn.process-one.net/ejabberd-modules
cd ejabberd-modules/mod_archive/trunk
./build.sh

现在使用以下 cmd 进入 ebin 目录并获取 ejabberd 存档插件的所有 *.beam 文件的列表。

root@ns1 [/ejabberd_archive_plugin/ejabberd-modules/mod_archive/trunk/ebin]# ls –l

在 ejabberd 设置和配置时,使用以下 cmd,您将获得所有 ejabberd *.beam 文件列表。

root@ns1 [/usr/lib64/ejabberd/ebin]# ls -l

现在使用以下 cmd 将所有 *.beam(存档插件)文件复制到 ejabberd ebin 目录

root@ns1 [/]# cp /ejabberd_archive_plugin/ejabberd-modules/mod_archive/trunk/ebin   /usr/lib64/ejabberd/ebin

现在转到以下 URL 并复制所有 sql 表查询并在 phpmyadmin(ejabberd 数据库)中运行

https://svn.process-one.net/ejabberd-modules/mod_archive/trunk/src/mod_archive_odbc_mysql.sql

现在使用以下 cmd 配置 ejjaberd.cfg

root@ns1 [/etc/ejabberd]# vi ejabberd.cfg 
Add the following line into ejabberd.cfg file in modules configuration section
{mod_archive_odbc, [{database_type, "mysql"}, {default_auto_save, true}, {enforce_default_auto_save, true}]},

现在重启 ejabberd 服务。

root@ns1 [/etc/ejabberd]# sudo service ejabberd restart

【讨论】:

  • 我在 android 中遇到了同样的问题,但我们有 OPENFIRE XMPP 服务器...您能提供任何想法吗?
【解决方案2】:

您必须为此创建单独的 Web 服务。因此,为什么我们可以处理已发送消息的历史记录。我们可以管理离线消息。

XEP-198 是唯一的解决方案。为您的服务器制作插件,使管理丢失的剩余消息变得容易。除了AFAIK,可能还有其他解决方案,这将是解决方案。

【讨论】:

  • 让我使用 XEP-198... 但还没有找到完美的解决方案。
  • 搜索此答案后,我无法得到完美的答案。但作为@Krunalsinh 的回答,我完成了制作单独Web 服务的工作。我不认为这个解决方案会在更长时间内起作用。 :-(
  • @Krunalsinh 你的回答自相矛盾......在一个地方你说创建网络服务,在一个地方你说实施XEP-198。将使用 http 连接调用 Web 服务,如果您实现 XEP - 198,则将通过 xmpp 连接套接字连接实现
  • @JaspreetSingh,我通过创建 Web 服务来管理这一切。一切都运行良好,但正如我所说,这不是完美的解决方案,而且速度也较慢。 :-(
  • Web 服务是目前唯一的解决方案,因为 XEP-198 没有启动
【解决方案3】:

每次重新连接到互联网后,您都应该重新登录。但是,请记住,如果您使用 相同的资源和相同的用户重新登录,即使它在线,服务器也会抛出流错误(由新连接替换),这将使您离线并且您不会收到任何信息。为此,请在重新登录之前先正确断开自己的连接。尝试搜索 mod Amp 模块。

【讨论】:

  • @JaspreetChhabra 我正在使用它但没有重新连接获取 java.lang.NullPointerException:尝试获取空数组的长度 W/AbstractXMPPConnection:在 org.jivesoftware.smack.util.stringencoder.Base64.encode( Base64.java:61) W/AbstractXMPPConnection: at org.jivesoftware.smack.util.stringencoder.Base64.encodeToString(Base64.java:43) W/AbstractXMPPConnection: at org.jivesoftware.smack.sasl.core.SCRAMSHA1Mechanism.evaluateChallenge( SCRAMSHA1Mechanis
【解决方案4】:

您可以修改存档插件以在其中保存消息 ID。

当用户上线时,使用收到的最后一条消息 ID 调用 Web 服务。服务器可以获取保存在服务器上的所有以后的消息。我以同样的方式创建它并且工作得很好。

【讨论】:

  • 我明白你在向我解释什么。但作为你的解释,直到我没有得到正确的解决方案。你能深入解释一下吗?我在连接 和恢复 但不能正常工作。发送请求工作正常。但我不会丢失通知。请给我适当的解决方案。任何帮助将不胜感激。
  • 我无法理解数据包 和简历
  • 您必须创建为您获取离线消息的 Web 服务。您必须为其创建一个插件,或者您可以修改存档插件。
  • XEP-198 仍然不适合,所以这是唯一的解决方案
  • 如果您使用的是 openfire,我可以给您完整的代码,但我没有使用 ejabber 服务器。您必须按照以下步骤操作: 1. 连接互联网后,通过 http 发送服务器收到的最后一条消息消息 ID 调用归档插件(归档插件保存所有消息。) 2. 服务器将回复在该消息 ID 之后收到的所有消息和回复
【解决方案5】:

您需要启用 "Stream Management" XEP-198 的连接来实现此目的。 Georg 就该主题写了一篇很好的博客文章:http://op-co.de/blog/posts/XEP-0198/ 基本上,它允许 stanza 确认流恢复,这正是您想要在例如 Wifi GSM 开关的情况下执行的操作。

我从堆栈跟踪中得出结论,您正在使用 aSmack(将 Smack 移植到 Android)。有一个在 Smack 中实现流管理的开放功能请求:SMACK-333。事实上,我最近开始着手实现,但无法命名 ETA。

【讨论】:

  • 我的问题是我将离线消息策略设置为“始终存储”,因此 XEP-0184 并不能真正帮助确定消息是否没有传递给接收者。提供这种情况: - 我有 2 个用户在聊天,称他们为 A 和 B - A 向 B 发送一条消息,而 B 的连接刚刚丢失 - 消息被丢弃并且 A 没有得到通知 - 在这种情况下,A 不知道消息已收到丢弃,它只是假设消息已传递到服务器,服务器最终会将其传递给 B - B 永远丢失消息
  • 我在连接时使用这样的节
  • 和简历 但不能正常工作。发送请求工作正常。但我不会迷路通知请给我正确的解决方案
  • 在一种情况下也会发生同样的事情。它有效。当我关闭手机时,我将从其他手机发送消息。并重新启动该设备,所有消息都已成功接收....
  • 我在 android 中遇到了同样的问题,但我们有 OPENFIRE XMPP 服务器...您能提供任何想法吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-22
  • 1970-01-01
  • 2014-02-28
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多