我曾用过一个好像叫Smack的java库,当时我遇到不少问题,这库本身不完善。
但你的问题实质是xmpp协议的问题,xmpp规定如果同一个账号(bare JID)可以同时在线多个,即获得不同的resource id。每个resource包含一个priority,默认为0。message只发给priority最高的一个,如果priority相同,则由应用自己决定如何实现。
openfire这里有一个属性route.all-resources,设置为true时允许消息发给所有相同bare JID的full JID,默认应该是false,你应该在管理平台上System Properties里设置route.all-resources为true。另外你说A自动下线,你确定管理平台上看到它下线了吗?我现在没有现成的openfire管理平台可以看到,但我记得它有一个选项是可以控制是否允许多登录的。

解决方案 »

  1. 还有,你可以在A上看下是否收到conflict。我估计你可能用的是同一个resource id登录,xmpp是不允许同一个resource登录多次的,实现多处登陆只能基于不同的resource。
    默认情况下,后一个登陆的session会踢掉前一个,前一个会收到一个conflict,根据xmpp协议,大致是这样的
    <stream:error>
      <conflict xmlns='urn:ietf:params:xml:ns:xmpp-streams'/>
    </stream:error>
    </stream:stream>
    你那边如何捕获这个消息,取决于你用的库
      

  2. 谢谢您的解答。我在系统属性里好像没有找到route.all-resources为true,改过一个xmpp.session.conflict-limit,改为2,没起到作用。现象是另一个手机提示send fail,无法接收和发送消息。
      

  3. 那我猜测是被踢了,你用的客户端是什么库,有没有session的消息回调之类的接口,需要找到能接受我上面提到的session conflict消息的接口。
    另外,上面我提到的那个属性,没有就自己新建一个。但是要注意这个和我这里提到的session conflict消息接口是两个不同的解决思路。你先确认是否能收到conflict,再考虑另一个情况
      

  4. 肯定有对连接的监听的。你使用的是asmack库么?
    如果是的话,有个ConnectionListener 。 在建立连接的时候实现监听,其中有个方法public void connectionClosedOnError(Exception arg0) {
    Logger.error(TAG, arg0.getMessage(), arg0);

    // 当被挤掉线的时候,不会自动重连
    // if(arg0.getMessage().contains("conflict")){ //被挤掉线,不会自动重连
    // }else if(arg0.getMessage().contains("Connection timed out")){//连接超时
    //            // 不做任何操作,会实现自动重连
    //        }
    }
    实现自己的业务逻辑即可 。
      

类似问题 »