无法通过 smack 连接到 XMPP 服务器:服务器没有响应

Posted

技术标签:

【中文标题】无法通过 smack 连接到 XMPP 服务器:服务器没有响应【英文标题】:Could not connect to the XMPP server via smack: No response from server 【发布时间】:2012-11-08 14:03:58 【问题描述】:

我被这个问题困住了,我无法解决它。

代码:

 ConnectionConfiguration config = new ConnectionConfiguration(host, port);
        config.setDebuggerEnabled(true);
        config.setSASLAuthenticationEnabled(true);
        config.setSecurityMode(ConnectionConfiguration.SecurityMode.enabled);

        XMPPConnection connection = new XMPPConnection(config);
try
            connection.connect();
            connection.login(login, password);
            //auth.authenticate(login, password, host);
        
        catch (XMPPException exc)
            exc.printStackTrace();
        

完整的堆栈跟踪:

/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/bin/java -Didea.launcher.port=7544 "-Didea.launcher.bin.path=/Applications/IntelliJ IDEA 11 CE.app/bin" -Dfile.encoding=UTF-8 -classpath "/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/deploy.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/dt.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/javaws.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/jce.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/jconsole.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/plugin.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/sa-jdi.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Classes/charsets.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Classes/classes.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Classes/jsse.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Classes/ui.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/ext/apple_provider.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/1.6.0_35-b10-428.jdk/Contents/Home/lib/ext/sunpkcs11.jar:/Users/dmitry/IdeaProjects/smacker/target/classes:/Users/dmitry/IdeaProjects/smacker/lib/smack-3.2.1.jar:/Users/dmitry/IdeaProjects/smacker/lib/smackx-3.2.1.jar:/Applications/IntelliJ IDEA 11 CE.app/lib/idea_rt.jar" com.intellij.rt.execution.application.AppMain Main
Connection failed. No response from server.: 
    at org.jivesoftware.smack.PacketReader.startup(PacketReader.java:119)
    at org.jivesoftware.smack.XMPPConnection.initConnection(XMPPConnection.java:568)
    at org.jivesoftware.smack.XMPPConnection.connectUsingConfiguration(XMPPConnection.java:527)
    at org.jivesoftware.smack.XMPPConnection.connect(XMPPConnection.java:953)
    at SessionsHandler.openSession(SessionsHandler.java:62)
    at Main.main(Main.java:16)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120)

Smack 调试输出:

在:

<stream:stream to="xmpp.odnoklassniki.ru" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
<starttls xmlns="urn:ietf:params:xml:ns:xmpp-tls"/>
<stream:stream to="odnoklassniki.ru" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">
</stream:stream>

输出:

<?xml version="1.0"?><stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" from="odnoklassniki.ru" version="1.0" xml:lang="en">
<stream:features><starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>X-ODKL-API</mechanism><mechanism>X-ODKL-BLOWFISH</mechanism><mechanism>PLAIN</mechanism></mechanisms><auth xmlns='http://jabber.org/features/iq-auth'/></stream:features>
<proceed xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>
<?xml version="1.0"?><stream:stream xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" from="odnoklassniki.ru" version="1.0" xml:lang="en">
<stream:features><mechanisms xmlns='urn:ietf:params:xml:ns:xmpp-sasl'><mechanism>X-ODKL-API</mechanism><mechanism>X-ODKL-BLOWFISH</mechanism><mechanism>PLAIN</mechanism></mechanisms><auth xmlns='http://jabber.org/features/iq-auth'/></stream:features>

远程登录:

dmitry@pro:~$ telnet xmpp.odnoklassniki.ru 5222
Trying 217.20.145.69...
Connected to xmpp.odnoklassniki.ru.
Escape character is '^]'.

【问题讨论】:

不幸的是,您发送的日志信息并没有太大帮助。您可能有异常堆栈跟踪吗? @AlexR 谢谢。我更新了问题。 【参考方案1】:

Smack 库 (3.2.2) 在第二个(在 starttls 之后)“stream:stream”数据包中需要 @id 属性。

这个属性是可选的,xmpp.odnoklassnki.ru 不发送它:

<stream:stream to="odnoklassniki.ru" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">

有两种方法可以解决这个问题:

修补 PacketReader 以将某种“假”ID 分配给流:流数据包中没有 @id 属性的连接 或要求 xmpp.odnoklassniki.ru 的管理员/开发人员在 stream:stream 数据包中添加(假的或真实的)ID 属性

这是 PacketReader:parsePackets() 方法的“修补”部分。请注意新的 connectionIdReceived 变量和对应的“if”条件:

// We found an opening stream. Record information about it, then notify
// the connectionID lock so that the packet reader startup can finish.
else if (parser.getName().equals("stream")) 
    // Ensure the correct jabber:client namespace is being used.
    if ("jabber:client".equals(parser.getNamespace(null))) 
        // Get the connection id.
        boolean connectionIdReceived = false;
        for (int i=0; i<parser.getAttributeCount(); i++) 
            if (parser.getAttributeName(i).equals("id")) 
                // Save the connectionID
                connectionID = parser.getAttributeValue(i);
                if (!"1.0".equals(parser.getAttributeValue("", "version"))) 
                    // Notify that a stream has been opened if the
                    // server is not XMPP 1.0 compliant otherwise make the
                    // notification after TLS has been negotiated or if TLS
                    // is not supported
                    releaseConnectionIDLock();
                
                connectionIdReceived = true;
            
            else if (parser.getAttributeName(i).equals("from")) 
                // Use the server name that the server says that it is.
                connection.config.setServiceName(parser.getAttributeValue(i));
            
        
        if (!connectionIdReceived) 
            connectionID = "<unspecified>";
            if (!"1.0".equals(parser.getAttributeValue("", "version"))) 
                // Notify that a stream has been opened if the
                // server is not XMPP 1.0 compliant otherwise make the
                // notification after TLS has been negotiated or if TLS
                // is not supported
                releaseConnectionIDLock();
            
        
    

【讨论】:

As per RFC 6120 the id attribute is mandatory, not optional。您应该联系服务器开发人员/管理员以了解损坏的实现。 @Flow ,根据RFC 3920(是的,已过时,但仍被广泛使用)它是可选的:“'id' 属性应仅用于来自接收实体的 XML 流标头中给发起实体”。似乎是新旧规范之间的差异。【参考方案2】:

我看到了几种可能性:

由于信任链或服务器提供的 *-name,您的库不接受您从服务器获取的证书:

主题:C=RU,L=莫斯科,O=Odnoklassniki Ltd,CN=*.odnoklassniki.ru

在“安全”模式下,您的库不喜欢该服务器提供的任何身份验证机制,因为只有两种非标准机制(X-ODKL-API、X-ODKL-BLOWFISH)和两种不太安全的机制(PLAIN,http://jabber.org/features/iq-auth)。

如果我不得不猜测它会是第二个。这不是大多数客户端库作者不太可能遇到的错误情况。关闭安全模式,然后重试。

【讨论】:

config.setSASLAuthenticationEnabled(false); config.setSecurityMode(ConnectionConfiguration.SecurityMode.disabled); - 同样的错误 当我尝试与adium 相同的配置时,它会在设置do strict certificate checks 选项时连接。你能给我一些信息吗?这是什么意思?我如何从服务器获取此证书。谢谢! 遇到与@DmitryZagorulkin 相同的错误【参考方案3】:

您的 XMPP 域似乎是错误的,这也可能是问题所在。而且您还将两个流标头发送到不同的域:

标题 1 到 xmpp.odnoklassniki.ru

<stream:stream to="xmpp.odnoklassniki.ru" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">

odnoklassniki.ru 的标题 2:

<stream:stream to="odnoklassniki.ru" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">

服务器总是回复 .... from="odnoklassniki.ru" .... 所以 odnoklassniki.ru 应该是您正确的 XMPP 域。

【讨论】:

美好的一天。但如果我在其他客户端输入xmpp.odnoklassniki.ru:5222。它工作正常。以 Adium 为例。更多信息在这里:security.stackexchange.com/questions/23972/… 当 Adium 能够连接时,这并不意味着您使用的是正确的 xmpp 域。你的服务器可能是非常容错的,它只提供了弱 PLAIN 和旧的遗留身份验证机制,其中 xmpp 域对于身份验证无关紧要。 你认为 smack 能够连接到这个服务器吗?我应该做什么样的配置?【参考方案4】:

试试这个...

它对我有用...尝试给资源名称也...我面临同样的问题 gioving 资源名称解决了它

 ConnectionConfiguration config;
config = new ConnectionConfiguration(ip, port, "Smack");
config.setSASLAuthenticationEnabled(false);
config.setReconnectionAllowed(true);
config.setCompressionEnabled(false);
config.setDebuggerEnabled(true);
connection = new XMPPConnection(config);
connection.connect();
if (connection.isConnected()) 
    connection.login(loginName, password);

【讨论】:

尝试查看即将到来的资源名称是什么......资源名称因操作系统而异 资源名称是什么?我在哪里可以读取可能的资源名称? config = new ConnectionConfiguration(ip, port, "Smack") 这里的“Smack”是资源名称..资源名称是我们正在使用的聊天系统的名称......比如smack或spark,或Skype 你使用 smack 所以这是你的资源名称...你把所有的库都正确了 让我们continue this discussion in chat

以上是关于无法通过 smack 连接到 XMPP 服务器:服务器没有响应的主要内容,如果未能解决你的问题,请参考以下文章

无法连接到本地 Openfire 服务器(使用 smack api)

Smack 连接到 Google 的 XMPP 服务 (gtalk) 会引发异常“SASLError using PLAIN: not-authorized”

无法使用 Smack 4.1 从 Android 连接 apache vysper XMPP 服务器

如何使用 Smack XMPP 库创建 SSL 连接?

XMPP 注销(Smack API)

无法发送和接收 XMPP 消息