Android/XMPP:连接类型更改后无法重新连接到服务器
Posted
技术标签:
【中文标题】Android/XMPP:连接类型更改后无法重新连接到服务器【英文标题】:Android/XMPP: Unable to reconnect to Server after Connection Type Changes 【发布时间】:2011-06-29 17:00:01 【问题描述】:我目前正在我大学的一个项目中工作,它是一个 android 应用程序,应该将数据传送到服务器。
为了做到这一点,我需要通过 XMPP 与服务器建立或多或少一致的连接。 100% 的时间都存在连接并不重要,但因为系统应该或多或少对用户不可见,所以用户交互应该是最小的。
服务器和客户端都是 xmpp 客户端。我使用jabber.org
作为 xmpp 服务器。
我有一个 Android-Service 正在建立与服务器的连接并传递数据,这工作正常。
现在我尝试在连接丢失或从 Wifi 更改为 GSM 时重新连接服务。我想尝试通过收听NETWORK_STATE_CHANGED_ACTION
的广播接收器来完成这项工作。但我什至没有走到这一步。
这是问题所在:我尝试运行该应用程序,然后只是禁用了我的 wifi。我的手机会自动切换到 GSM,然后我失去了连接(这是我预料到的)。但是当我尝试手动重新连接(例如重新启动服务)时,我从服务器收到错误。此外,我的状态仍然是“可用”。从那一刻起,我需要很长时间才能再次连接。
06-29 18:12:14.888: WARN/System.err(14246): resource-constraint(500)
06-29 18:12:14.890: WARN/System.err(14246): at org.jivesoftware.smack.NonSASLAuthentication.authenticate(NonSASLAuthentication.java:110)
06-29 18:12:14.890: WARN/System.err(14246): at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:404)
06-29 18:12:14.890: WARN/System.err(14246): at org.jivesoftware.smack.XMPPConnection.login(XMPPConnection.java:349)
....
我实际上已连接到 xmpp 服务器,但它没有传递我的消息:
06-29 18:12:14.882: INFO/System.out(14246): 06:12:14 nachm. RCV (1079704816): <iq type='error' id='7rhk4-70'><error code='500' type='wait'><resource-constraint xmlns='urn:ietf:params:xml:ns:xmpp-stanzas'/></error></iq>
有时我没有收到错误消息,但仍然没有消息被传递。
所以我认为服务器不允许我连接,因为我在尝试重新连接之前没有断开连接。我觉得这很奇怪,因为我认为您甚至可以将多个客户连接到一个帐户。
我发布了一些我认为可能相关的代码:
public void connectToServer() throws XMPPException
ConnectionConfiguration config = new ConnectionConfiguration(
serverADD, port,
service);
connection = new XMPPConnection(config);
connection.connect();
SASLAuthentication.supportSASLMechanism("PLAIN", 0);
connection.login(user_JID,password);
Presence presence = new Presence(Presence.Type.available);
presence.setStatus("available");
presence.setPriority(24);
presence.setMode(Presence.Mode.available);
connection.sendPacket(presence);
这就是我发送消息的方式:
public void sendMessage(String message, String recipient) throws XMPPException
chat = connection.getChatManager().createChat(recipient, this);
chat.sendMessage(message);
有人知道如何解决这个问题吗?只要我的消息被传递到服务器,我什至会使用“肮脏”的技巧。
顺便说一句:发送者和接收者的 jid 总是相同的(在初始设置之后)。以防万一有人认为这很重要。
【问题讨论】:
你使用 smack 还是 (a)smack?如果(a)smack,哪个?如果你重新连接同一个资源,而服务器仍然认为同一个资源有有效的连接,就会发生资源冲突。如何处理这取决于服务器策略。 我使用 smack,但现在我很困惑是哪一个。我使用 asmack 并且遇到了问题,然后互联网上的某个人有一个教程来修补 smack 版本。我盲目地遵循这个,因为我想摆脱那个错误(甚至不记得它是什么)。通过一些网络搜索,我可能会找出它是哪一个以及它是什么类型的补丁。我是否可以使用自动更改的新资源登录,每次重新登录并在每个步骤中计算优先级,以便消息仍然传递?感觉有点不对。 因此我不会更改同一设备上的资源。事实上,资源的工作是在 XMPP 中识别同一个端点。您所要做的就是配置 XMPP 服务器,以便在建立具有相同资源的新连接时终止旧连接。 您好,我遇到过这样的问题。你有解决方案吗?请帮帮我。谢谢! 【参考方案1】:Smack 断开连接期间的死锁
正如 Airsource Ltd. 在他的评论中提到的那样:Smack 在 disconnect()
中遇到了死锁,它被记录为 SMACK-278。我有 made a commit that fixes this in my smack fork。
Android 重新连接处理
对于网络故障转移,请查看GTalkSMS receiver。它将发出一个 ACTION_NETWORK_CHANGED 意图,带有布尔附加值“可用”和“故障转移”。当“available=false”和“fallover=false”时,您的服务应该“停止”连接。如何“停止”连接取决于您。有时即使修复了 SMACK-278,disconnect() 也需要很长时间,这就是我们执行 disconnect in an thread that will abort after x seconds 然后创建一个新的 Connection 实例的原因。当收到带有“available=true”的意图时,我们会重新连接。
您将在 GTalkSMS 源代码中找到其他示例。我的应用程序永久运行,它实现了稳定但不是 100% 可用的连接(因为 WLAN GSM 开关)。
【讨论】:
非常感谢,我从那个源代码中学到了很多东西。我不太确定我是否已经解决了重新连接问题,但我现在正在解决这个问题。我想我应该让应用程序运行一段时间看看它做了什么...... 长时间断开连接似乎是由于断开连接中的 BufferedReader.close() 和 PacketReader 中的 BufferedReader.read() 之间出现死锁。有一个补丁 - 见issues.igniterealtime.org/browse/SMACK-278以上是关于Android/XMPP:连接类型更改后无法重新连接到服务器的主要内容,如果未能解决你的问题,请参考以下文章
Socket.io 客户端在突然断开连接后无法重新连接到服务器
UCanAccess - 使用 keepMirror 后无法重新连接到 Access 数据库