如何使用Eclipse Paho在Java MQTT客户端上接收时发布消息

时间:2015-07-01 12:46:37

标签: java eclipse mqtt

我正在尝试使用Eclipse Paho在Java中的MQTT客户端上实现某些功能。目标是订阅主题,当收到消息时,客户端会发送另一个主题的消息。

这看起来很容易,但我有一个奇怪的问题,我无法解决。这是我的代码:

import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.IMqttToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.eclipse.paho.client.mqttv3.MqttClient;
import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;

public class MqttOperations implements MqttCallback {

    MqttClient sampleClient;
    MqttConnectOptions connOpts;

    public MqttOperations() {
    }

    public static void main(String[] args) throws InterruptedException {
        new MqttOperations().launchMqttClient();
    }


    public void launchMqttClient() throws InterruptedException {
         try {
                MemoryPersistence persistence = new MemoryPersistence();
                sampleClient = new MqttClient("tcp://broker.mqttdashboard.com:1883", "iamaclient", persistence);
                connOpts = new MqttConnectOptions();
                connOpts.setCleanSession(true);
                sampleClient.connect(connOpts);
                sampleClient.subscribe("topic/example/ofmessage");
                sampleClient.setCallback(this);

            } catch(MqttException me) {
                System.out.println("reason "+me.getReasonCode());
                System.out.println("msg "+me.getMessage());
                System.out.println("loc "+me.getLocalizedMessage());
                System.out.println("cause "+me.getCause());
                System.out.println("excep "+me);
                me.printStackTrace();
            }
    }


    @Override
    public void connectionLost(Throwable cause) {
        // TODO Auto-generated method stub  

    }

    @Override
    public void messageArrived(String topic, MqttMessage message) throws MqttException
    {
        System.out.println("Received: " + message.toString());  
        try{
            System.out.println("Publishing message: i am the answer");
            MqttMessage ans = new MqttMessage("i am the answer".getBytes());
            ans.setQos(2);
            sampleClient.publish("topic/example/ofanswer", ans);
            System.out.println("Message published");

        }catch(MqttException me){
                System.out.println("reason "+me.getReasonCode());
                System.out.println("msg "+me.getMessage());
                System.out.println("loc "+me.getLocalizedMessage());
                System.out.println("cause "+me.getCause());
                System.out.println("excep "+me);
                me.printStackTrace();
        }

    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {

    }

}

问题是,这个程序只运行一次。收到消息后,将发送此消息的答案,但似乎消息“已发布消息”从未显示在屏幕上,并且客户端不会收到任何其他消息。 我的印象是sampleClient.publish("topic/example/ofanswer", ans);行永远不会完成执行。 有谁知道它是怎么来的,请问如何解决我的问题?

2 个答案:

答案 0 :(得分:3)

我今天遇到了类似的问题。当我读到an other question with two connections时,我明白了:你需要两个MqttClient实例。一个用于发布,一个用于订阅。不幸的是,我没有找到这方面的文件。

顺便说一下。在我第一次使用两个客户端时,我给了它们相同的ID(逻辑上它应该是相同的连接)。但是第二个连接断开了第一个连接。当我开始使用两个不同的ID时,它开始工作。

答案 1 :(得分:0)

Dominik Obermaier是对的:问题是你阻止了messageArrived。具体来说,MqttClient.publish等待直到收到消息的传递通知 - 但是MqttClient工作线程永远不会检索它,因为它正在等待messageArrived中的通知!

双客户端解决方案有效,因为其他客户端的工作线程可以自由地从套接字检索通知,但正确的解决方案是从messageArrived中发布QoS 0(因为QoS 0消息不需要确认传递)或使用不等待传递消息的API,例如MqttTopic.publish。