NullPoInterException通过SMACK 4.2.0进行XMPP连接时



我打算使用smack通过firebase ccs发送消息。我为我的Web应用程序修改了一个简单的CCS客户端,但是当我尝试建立连接时,会导致例外。我正在使用 SMACK 4.2.0

这是连接的过程。

1(我的客户端中的连接方法:

public void connect() throws XMPPException{
        try{
            config = XMPPTCPConnectionConfiguration.builder()
                    .setPort(Config.FCM_PORT)
                    .setHost("fcm-xmpp.googleapis.com")
                    .setXmppDomain("googleapis.com")
                    .setSecurityMode(/*Default; Explicit setting for emphasis*/SecurityMode.ifpossible)
                    .setSendPresence(true)
                    .setUsernameAndPassword(fcmServerUsername, mApiKey)
                    .setSocketFactory(SSLSocketFactory.getDefault())
                    .setDebuggerEnabled(mDebuggable)/* Launch a window with info about packets sent and received */
                    .build();
        }
        catch(XmppStringprepException e){
            e.printStackTrace();
        }
        connection = new XMPPTCPConnection(config);

        // Configuring Automatic reconnection
        ReconnectionManager manager = ReconnectionManager.getInstanceFor(connection);
        manager.setReconnectionPolicy(ReconnectionManager.ReconnectionPolicy.RANDOM_INCREASING_DELAY);
        manager.enableAutomaticReconnection();
        // Connect now then login
        try{
            connection.connect();
            connection.login();
        }
        // TODO: Handle the exceptions if possible appropriately
        catch(SmackException sme){
            logger.severe(sme.getMessage());
            sme.printStackTrace();
        }
        catch(IOException ioe){
            logger.severe(ioe.getMessage());
            ioe.printStackTrace();
        }
        catch(InterruptedException ie){
            logger.severe("Connection got interrupted!!");
            ie.printStackTrace();
        }
    }

2(我追踪了例外,然后在这里得到它:( Smack的来源(

在线-HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());

// AbstractXMPPConnection.java
protected List<HostAddress> populateHostAddresses() {
        List<HostAddress> failedAddresses = new LinkedList<>();
        if (config.hostAddress != null) {
            hostAddresses = new ArrayList<>(1);
            HostAddress hostAddress = new HostAddress(config.port, config.hostAddress);
            hostAddresses.add(hostAddress);
        }
        else if (config.host != null) {
            hostAddresses = new ArrayList<HostAddress>(1);
            HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
            if (hostAddress != null) {
                hostAddresses.add(hostAddress);
            }
        } else {
            // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
            hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
        }
        // Either the populated host addresses are not empty *or* there must be at least one failed address.
        assert(!hostAddresses.isEmpty() || !failedAddresses.isEmpty());
        return failedAddresses;
    }

例外是 nullpoInterException ,我发现getDNSResolver()返回null。在我提到的所有来源中,与DNS解析器没有任何关系,因为它应该由Smack内部处理。所以我的问题是,我是否错过了建立连接的一些关键配置或步骤?

编辑:我在这里问,因为Smack是广阔的lib,并且可能有人知道我可能会错过。我无法直接设置DNSresolver

编辑:回答更新

这不是Smack源的错误,作为其4.2.0的升级指南,明确提及:

**

API更改

**

警告:此列表可能未完成

介绍了ConnectionConfiguration.setHostAddress(InetAddress)

在先前版本的Smack中, ConnectionConfiguration.setHost(String)可用于设置 XMPP服务的主机IP地址。由于 添加了DNSSEC支持。您必须使用新的连接配置 ConnectionConfiguration.setHostAddress(InetAddress)而不是。


这似乎是一个错误,因为 我通过提供主机地址(应该是从{host,domain}推断出来的(解决了它。那么,我怎么知道提供主机地址?

窍门在这里:( smack'source(

// AbstractXMPPConnection.java
if (config.hostAddress != null) {
            hostAddresses = new ArrayList<>(1);
            HostAddress hostAddress = new HostAddress(config.port, config.hostAddress);
            hostAddresses.add(hostAddress);
        }
        else if (config.host != null) {
            hostAddresses = new ArrayList<HostAddress>(1);
            HostAddress hostAddress = DNSUtil.getDNSResolver().lookupHostAddress(config.host, config.port, failedAddresses, config.getDnssecMode());
            if (hostAddress != null) {
                hostAddresses.add(hostAddress);
            }
        } else {
            // N.B.: Important to use config.serviceName and not AbstractXMPPConnection.serviceName
            hostAddresses = DNSUtil.resolveXMPPServiceDomain(config.getXMPPServiceDomain().toString(), failedAddresses, config.getDnssecMode());
        }

您可以查看是否在此处及以来的块,并且由于else if (config.host != null)块出现了例外,我提供了hostaddress,因此它永远不会进入该块并起作用。

我知道这是围绕实际问题的黑客攻击,但这似乎是Smack 4.2.0中的错误,除非有人反驳我。

奖励信息:如果在纠正此问题后,您在登录过程中在基本64中获得另一个例外,请参阅此 - 使用smack 4.1使用nullpoInterException在登录过程中使用smack client

不确定在4.2.0中,但在4.2.2(和较新(中,您需要Smack-resolver-dnsjava-4.2.2.jar在您的classpath中,Smack呼叫DNSutil包含在软件包中,如果类不存在,它将返回NullPoInterException。

希望这有所帮助!大卫

最新更新