背景
我一直在玩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客户端以非阻塞方式连接到代理?我一路上都错过了什么吗?
答案 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();
}