如何解决paho mqtt客户端的异步连接问题?

时间:2017-10-05 08:08:13

标签: java asynchronous mqtt paho

背景

我一直在玩MQTT项目并遇到了一个奇怪的问题。我使用paho作为我的MQTT客户端,使用VerneMQ作为代理。

VerneMQ代理服务已启动并运行,我可以通过runnnig netstat进行确认,我可以看到127.0.0.1:1883条目处于LISTENING模式。

这是我的客户代码:

public class Producer implements MqttCallback {

    private String brokerUri;
    private String clientId;

    public Producer(String brokerUri, String clientId){
        this.brokerUri = brokerUri;
        this.clientId = clientId;
    }

    public void doProduce(String topic, String payload){
        MemoryPersistence memoryPersistence = new MemoryPersistence();

        try {
            MqttAsyncClient mqttAsyncClient = new MqttAsyncClient(brokerUri, clientId, memoryPersistence);
            MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
            mqttConnectOptions.setCleanSession(true);
            mqttAsyncClient.setCallback(this);
            mqttAsyncClient.connect(mqttConnectOptions);
            MqttMessage mqttMessage = new MqttMessage();
            mqttMessage.setPayload(payload.getBytes());
            mqttAsyncClient.publish(topic, mqttMessage);
        } catch (MqttException e) {
            e.printStackTrace();
        }
    }

    public void connectionLost(Throwable throwable) {

    }


    public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {

    }


    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        System.out.println("Message delivered!");
    }
}

以下是我的主要课程

public class Main {
    public static void main(String[] args) {
        Producer producer = new Producer("tcp://127.0.0.1:1883", "producer1");
        producer.doProduce("dummyTopic", "dummyMessage");
    }
}

问题

当我运行我的应用程序时,我在输出中看到Client is not connected (32104)异常。

如果我在mqttAsyncClient.connect(mqttConnectOptions);课程中将行mqttAsyncClient.connect(mqttConnectOptions).waitForCompletion();更改为Producer,我可以成功连接到经纪人,我可以在输出中看到Message delivered!

如果我没有弄错,waitForCompletion()将阻止通话直到收到回复。通过添加这一行,我已经有效地将我的AsyncClient连接更改为阻塞连接,这对我来说不是理想的方法。

问题

如何解决此问题,以便paho MQTT客户端以非阻塞方式连接到代理?我一路上都错过了什么吗?

1 个答案:

答案 0 :(得分:4)

这涵盖在IMqttAsyncClient

的文档中
 IMqttToken token method(parms, Object userContext, IMqttActionListener callback)
     

在此表单中,使用该方法注册回调。回调   当操作成功或失败时将收到通知。回调是   在MQTT客户端管理的线程上调用,因此它很重要   处理在回调中被最小化。如果没有操作的话   MQTT客户端将被禁止。例如要通知(称为   当连接完成时:

IMqttToken conToken;
  conToken = asyncClient.connect("some context", new MqttAsyncActionListener() {
      public void onSuccess(IMqttToken asyncActionToken) {
        log("Connected");
      }

      public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
        log ("connect failed" +exception);
      }
});
     

可以将可选的上下文对象传递给将要执行的方法   然后在回调中提供。上下文由...存储   令牌中的MQTT客户端)然后返回给调用者。该   令牌被提供给回调方法,然后上下文可以   被访问。

所以你的try / catch块应该是这样的:

try {
  MqttAsyncClient mqttAsyncClient = new MqttAsyncClient(brokerUri, clientId, memoryPersistence);
  MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
  mqttConnectOptions.setCleanSession(true);
  mqttAsyncClient.setCallback(this);
  mqttAsyncClient.connect(mqttConnectOptions, null, new MqttAsyncActionListener() {
    public void onSuccess(IMqttToken asyncActionToken) {
      MqttMessage mqttMessage = new MqttMessage();
      mqttMessage.setPayload(payload.getBytes());
      mqttAsyncClient.publish(topic, mqttMessage);
    }

    public void onFailure(IMqttToken asyncActionToken, Throwable exception) {
      exception.printStackTrace();
    }
});

} catch (MqttException e) {
  e.printStackTrace();
}