使用没有自动重新连接的 MqttAsyncClient 时如何检测 "Connection refused"?

How to detect "Connection refused" when using MqttAsyncClient with no automatic reconnect?

我正在使用 Eclipse Paho Java 客户端进行连接。这是我的扩展回调:

protected IMqttAsyncClient mClient;

private final MqttCallbackExtended mCallback = new MqttCallbackExtended() {
    @Override
    public void connectComplete(boolean reconnect, String brokerAddress) {
        Log.d(LOG_TAG, "connectComplete " + brokerAddress);
    }

    @Override
    public void connectionLost(Throwable ex) {
        Log.d(LOG_TAG, "connectionLost", ex);
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken deliveryToken) {
        Log.d(LOG_TAG, "deliveryComplete " + deliveryToken);
    }

    @Override
    public void messageArrived(String topic, MqttMessage mqttMessage) throws Exception {
        Log.d(LOG_TAG, "messageArrived " + topic);
    }
};

这里是连接代码:

protected void connect() throws MqttException {
    Log.d(LOG_TAG, "connect");

    MqttConnectOptions connectOptions = new MqttConnectOptions();
    connectOptions.setCleanSession(true);
    connectOptions.setAutomaticReconnect(false);
    connectOptions.setUserName(MQTT_USERNAME);
    connectOptions.setPassword(MQTT_PASSWORD.toCharArray());

    mClient = new MqttAsyncClient(mBrokerUri, mClientName, new MemoryPersistence());
    mClient.setCallback(mCallback);
    mClient.connect(connectOptions);

    Debug d = ((MqttAsyncClient) mClient).getDebug();
    d.dumpClientDebug();
}

我不使用自动重新连接功能,但想在我自己的自定义代码中处理重新连接,因为我需要自定义延迟。

出于测试目的,我还没有启动 MQTT 代理并尝试连接。

我希望在 connectionLost 回调方法中检测到 初始 连接失败,但它没有被调用。

MqttException也没有抛出。

当我检查 paho0.log.0 日志文件时,我看到那里的连接失败 -

FINE     17-03-09  07:55:33.0726    al.TCPNetworkModule  start                      61  ef978a39c826cd6d4ad22f20d5abe6c236eddb060b5d765a1fe2e1d79837fcc8: Failed to create TCP socket
Throwable occurred: java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:70)
    at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:650)
    at java.lang.Thread.run(Thread.java:745)
FINE     17-03-09  07:55:33.0727    nternal.ClientComms  connectBG:run              61  ef978a39c826cd6d4ad22f20d5abe6c236eddb060b5d765a1fe2e1d79837fcc8: connect failed: unexpected exception
Throwable occurred: Unable to connect to server (32103) - java.net.ConnectException: Connection refused: connect
    at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:79)
    at org.eclipse.paho.client.mqttv3.internal.ClientComms$ConnectBG.run(ClientComms.java:650)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.net.ConnectException: Connection refused: connect
    at java.net.DualStackPlainSocketImpl.waitForConnect(Native Method)
    at java.net.DualStackPlainSocketImpl.socketConnect(DualStackPlainSocketImpl.java:85)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:188)
    at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:172)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:392)
    at java.net.Socket.connect(Socket.java:589)
    at org.eclipse.paho.client.mqttv3.internal.TCPNetworkModule.start(TCPNetworkModule.java:70)
    ... 2 more
FINE     17-03-09  07:55:33.0732    nternal.ClientComms  shutdownConnection         61  ef978a39c826cd6d4ad22f20d5abe6c236eddb060b5d765a1fe2e1d79837fcc8: state=DISCONNECTING
FINE     17-03-09  07:55:33.0732    ernal.CommsCallback  stop                       61  ef978a39c826cd6d4ad22f20d5abe6c236eddb060b5d765a1fe2e1d79837fcc8: stopped
FINE     17-03-09  07:55:33.0733    nal.CommsTokenStore  quiesce                    61  ef978a39c826cd6d4ad22f20d5abe6c236eddb060b5d765a1fe2e1d79837fcc8: resp=Client is currently disconnecting (32102)

但是如何在我的代码中检测到连接失败? (以便我可以启动稍后的重新连接)。

更新:

将此问题报告为 Bug #336

目前检测异步客户端初始连接失败的唯一方法是再传递一个回调:

private final IMqttActionListener mConnectionCallback = new IMqttActionListener() {
    @Override
    public void onSuccess(IMqttToken asyncActionToken) {
        Log.d(LOG_TAG, "onSuccess " + asyncActionToken);
        // do nothing, this case is handled in mCallback.connectComplete method
    }

    @Override
    public void onFailure(IMqttToken asyncActionToken, Throwable ex) {
        Log.d(LOG_TAG, "onFailure " + asyncActionToken, ex);
        // initial connect has failed
    }
};

mClient = new MqttAsyncClient(mBrokerUri, mClientName, new MemoryPersistence());
mClient.setCallback(mCallback);
mClient.connect(connectOptions, null, mConnectionCallback);