调用 XMPPTCPConnection.login (Smack-4.1.0) 时抛出 SmackException$NoResponseException

Posted

技术标签:

【中文标题】调用 XMPPTCPConnection.login (Smack-4.1.0) 时抛出 SmackException$NoResponseException【英文标题】:SmackException$NoResponseException thrown when calling XMPPTCPConnection.login (Smack-4.1.0) 【发布时间】:2015-04-07 18:17:37 【问题描述】:

环境:

服务器:OpenFire v3.9.3。 客户端操作系统:Linux 服务器操作系统:Linux Java:1.8.0_40 Smack:smack-core-4.10、smack-im-4.1.0、smack-tcp-4.1.0、smack-sasl-provided-4.1.0

这是我的测试客户端代码:

public class XMPPClientTest

    public static void main(String[] args)
    

        XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
                .setHost("xmpp.domain")
                .setServiceName("xmpp.domain")
                .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
                .setDebuggerEnabled(true)
                .setResource("Smack-client")
                .build();

        AbstractXMPPConnection conn1 = new XMPPTCPConnection(config);
        try
        
            System.out.println("connecting");
            conn1.connect();
            System.out.println("connected");

            System.out.println("logging in");
            conn1.login("user", "password");
            System.out.println("logged in");

            ChatManager chatmanager = ChatManager.getInstanceFor(conn1);
            Chat newChat = chatmanager.createChat("user@xmpp.domain");

            newChat.sendMessage("Goodbye World!");
            conn1.disconnect();
        
        catch (IOException | SmackException | XMPPException ioe)
        
            ioe.printStackTrace();
        
    

这是输出

connecting
11:49:40 AM SENT (0): <stream:stream xmlns='jabber:client' to='xmpp.domain' xmlns:stream='http://etherx.jabber.org/streams' version='1.0' xml:lang='en'>
11:49:40 AM RECV (0): <?xml version='1.0' encoding='UTF-8'?><stream:stream xmlns:stream="http://etherx.jabber.org/streams" xmlns="jabber:client" from="xmpp.domain" id="3d0a3800" xml:lang="en" version="1.0">
11:49:40 AM RECV (0): <stream:features><starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"></starttls><mechanisms xmlns="urn:ietf:params:xml:ns:xmpp-sasl"><mechanism>PLAIN</mechanism><mechanism>CRAM-MD5</mechanism><mechanism>DIGEST-MD5</mechanism></mechanisms><compression xmlns="http://jabber.org/features/compress"><method>zlib</method></compression><auth xmlns="http://jabber.org/features/iq-auth"/></stream:features>
logging in
11:49:40 AM SENT (0): <auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'>=</auth>
11:49:40 AM RECV (0): <challenge xmlns="urn:ietf:params:xml:ns:xmpp-sasl">cmVhbG09InhtcHAua2lkY2hlY2suY29tIixub25jZT0iYXpqS2N3UUh3S2RjTTVQeWt4OEo2YmdsM1VoMk9JQkVTallBWXFLOSIscW9wPSJhdXRoIixjaGFyc2V0PXV0Zi04LGFsZ29yaXRobT1tZDUtc2Vzcw==</challenge>
org.jivesoftware.smack.SmackException$NoResponseException: No response received within reply timeout. Timeout was 5000ms (~5s). Used filter: No filter used or filter was 'null'.
    at org.jivesoftware.smack.SmackException$NoResponseException.newWith(SmackException.java:106)
    at org.jivesoftware.smack.SmackException$NoResponseException.newWith(SmackException.java:85)
    at org.jivesoftware.smack.SASLAuthentication.authenticate(SASLAuthentication.java:250)
    at org.jivesoftware.smack.tcp.XMPPTCPConnection.loginNonAnonymously(XMPPTCPConnection.java:365)
    at org.jivesoftware.smack.AbstractXMPPConnection.login(AbstractXMPPConnection.java:452)
    at org.jivesoftware.smack.AbstractXMPPConnection.login(AbstractXMPPConnection.java:427)
    at com.forge.label.app.driver.test.XMPPClientTest.main(XMPPClientTest.java:39)
Apr 07, 2015 11:49:45 AM org.jivesoftware.smack.AbstractXMPPConnection callConnectionClosedOnErrorListener
WARNING: Connection closed with error
java.lang.NullPointerException
    at org.jivesoftware.smack.util.stringencoder.Base64.decode(Base64.java:86)
    at org.jivesoftware.smack.sasl.SASLMechanism.challengeReceived(SASLMechanism.java:229)
    at org.jivesoftware.smack.SASLAuthentication.challengeReceived(SASLAuthentication.java:328)
    at org.jivesoftware.smack.SASLAuthentication.challengeReceived(SASLAuthentication.java:313)
    at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.parsePackets(XMPPTCPConnection.java:1040)
    at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader.access$200(XMPPTCPConnection.java:937)
    at org.jivesoftware.smack.tcp.XMPPTCPConnection$PacketReader$1.run(XMPPTCPConnection.java:952)
    at java.lang.Thread.run(Thread.java:745)

我可以使用 Pidgin 等 IM 客户端连接到服务器。但是当我尝试使用 Smack 库时,我得到了上述错误。我为这个问题找到的唯一“解决方案”是调用 XMPPTCPConnectionConfiguration.setSecurityMode(SecurityMode.disabled) 但这在我的情况下不起作用。

从调试输出看来,服务器正在发送质询,而客户端正在忽略它。

任何帮助将不胜感激。

【问题讨论】:

您是否阅读并遵循github.com/igniterealtime/Smack/wiki/… 中的说明? 我确实读过,但没有发现任何非常有趣的东西。尽管出于尽职调查,我尝试更改我的 pom 以模仿您发送的链接中所代表的内容,并且低,现在它可以工作了。感谢回复 请回答您自己的问题,解释您做错了什么,然后将答案标记为已接受。 @preston.m.price 你有解决方案吗? @Flow 你想回答这个问题吗? 【参考方案1】:

就我而言,我在 pom.xml 中删除了下面的依赖项

然后,该错误不再出现。

    <dependency>
       <groupId>org.igniterealtime.smack</groupId>
       <artifactId>smack-extensions</artifactId>
       <version>4.1.4</version>
    </dependency>

【讨论】:

【参考方案2】:

使用 smack 的 Xmpp 连接将在您调用 connect() 时建立。但它只是启动连接过程。连接将在后台建立(单独的线程)。

在您的情况下,您在 connect() 语句之后登录到 xmpp 服务器。到那时登录语句被执行,连接可能无法建立。因此,通过实现 ConnectionListener 接口使用回调方法进行连接,如下所示:

XMPPTCPConnection connection = new XMPPTCPConnection(config);
    connection.addConnectionListener(new ConnectionListener() 

        @Override
        public void reconnectionSuccessful() 
        

        @Override
        public void reconnectionFailed(Exception arg0) 
        

        @Override
        public void reconnectingIn(int arg0) 
        

        @Override
        public void connectionClosedOnError(Exception arg0) 
        

        @Override
        public void connectionClosed() 
        

        @Override
        public void connected(XMPPConnection arg0) 
            System.out.println("Connected to xmpp service....");
            try 
                connection.login("username", "password");
                System.out.println("Logged in to xmpp service....");
             catch (Exception e) 
                e.printStackTrace();
            

        

        @Override
        public void authenticated(XMPPConnection arg0, boolean arg1) 
            // TODO Auto-generated method stub

        
    );
    connection.connect();

【讨论】:

答案错误:connect()是同步调用。 感谢@Flow 的反馈。调用 login() 然后调用 connect() 应该可以工作。为什么它不起作用? 我说connect()是同步调用,你说它是异步的(例如,“……当你调用connect()时。但它只是启动连接过程。连接将在后台建立.. "),因此您建议在连接侦听器中调用login()。但这不是必需的,因此不需要这个答案的建议.. 但是我在答案中给出的代码工作正常(我在我的应用程序中使用它)。但是在 connect() 之后立即调用 login() 对我不起作用。你能告诉我它不起作用的原因吗? 不,但我可以说这不可能是它现在工作的原因。在您实施此更改时,可能发生了其他变化

以上是关于调用 XMPPTCPConnection.login (Smack-4.1.0) 时抛出 SmackException$NoResponseException的主要内容,如果未能解决你的问题,请参考以下文章

java三种调用方式(同步调用/回调/异步调用)

LINUX系统调用

引用调用 vs 复制调用调用

RPC 调用和 HTTP 调用的区别

js方法调用

深入理解Java虚拟机——方法调用(解析调用)