我正在尝试使用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);
行永远不会完成执行。
有谁知道它是怎么来的,请问如何解决我的问题?
答案 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。