MQTT客户端监控连接状态事件

MQTT客户端监控连接状态事件

项目采用paho.mqtt.java客户端,需要监控连接状态变更事件,以进行异常维测和处理。

代码中提供了MqttCallback接口如下:

org.eclipse.paho.client.mqttv3-1.2.0-sources.jar!\org\eclipse\paho\client\mqttv3\MqttClient.java

public void setCallback(MqttCallback callback) {
   aClient.setCallback(callback);
}

其中MqttCallback 接口定义如下:

public interface MqttCallback {
   /** 连接断连
    * This method is called when the connection to the server is lost.
    *
    * @param cause the reason behind the loss of connection.
    */
   public void connectionLost(Throwable cause);

   /** 消息收到回调的缺省回调,如果subscribe(String topicFilter, int qos, IMqttMessageListener messageListener)指定了 IMqttMessageListener 会覆盖该回调,也即:使用IMqttMessageListener 回调,MqttCallback 中的messageArrived回调无响应了
    * This method is called when a message arrives from the server.
    *
    * <p>
    * This method is invoked synchronously by the MQTT client. An
    * acknowledgment is not sent back to the server until this
    * method returns cleanly.</p>
    * <p>
    * If an implementation of this method throws an <code>Exception</code>, then the
    * client will be shut down.  When the client is next re-connected, any QoS
    * 1 or 2 messages will be redelivered by the server.</p>
    * <p>
    * Any additional messages which arrive while an
    * implementation of this method is running, will build up in memory, and
    * will then back up on the network.</p>
    * <p>
    * If an application needs to persist data, then it
    * should ensure the data is persisted prior to returning from this method, as
    * after returning from this method, the message is considered to have been
    * delivered, and will not be reproducible.</p>
    * <p>
    * It is possible to send a new message within an implementation of this callback
    * (for example, a response to this message), but the implementation must not
    * disconnect the client, as it will be impossible to send an acknowledgment for
    * the message being processed, and a deadlock will occur.</p>
    *
    * @param topic name of the topic on the message was published to
    * @param message the actual message.
    * @throws Exception if a terminal error has occurred, and the client should be
    * shut down.
    */
   public void messageArrived(String topic, MqttMessage message) throws Exception;

   /** 消息publish完成回调
    * Called when delivery for a message has been completed, and all
    * acknowledgments have been received. For QoS 0 messages it is
    * called once the message has been handed to the network for
    * delivery. For QoS 1 it is called when PUBACK is received and
    * for QoS 2 when PUBCOMP is received. The token will be the same
    * token as that returned when the message was published.
    *
    * @param token the delivery token associated with the message.
    */
   public void deliveryComplete(IMqttDeliveryToken token);
}

可以通过connectionLost回调进行断连提示,但是重连的状态回调呢?

(说明:可以通过mqttClient.connect(mqttConnectOptions);中的

mqttConnectOptions.setAutomaticReconnect(true); // 自动重连

设置自动重连

 

哈哈。paho.mqtt.java用了一个很有意思且巧妙的方法处理,如下:

/**
 * Extension of {@link MqttCallback} to allow new callbacks
 * without breaking the API for existing applications.
 * Classes implementing this interface can be registered on
 * both types of client: {@link IMqttClient#setCallback(MqttCallback)}
 * and {@link IMqttAsyncClient#setCallback(MqttCallback)}
 */
public interface MqttCallbackExtended extends MqttCallback {
   
   /**
    * Called when the connection to the server is completed successfully.
    * @param reconnect If true, the connection was the result of automatic reconnect.
    * @param serverURI The server URI that the connection was made to.
    */
   public void connectComplete(boolean reconnect, String serverURI);

}

使用时调用:mqttClient.setCallback(callback); 传入的callback采用 MqttCallbackExtended 的实现类就可以得到 connectComplete回调了。具体实现可以详见代码。
一句话:MqttCallbackExtended 应该是后期扩展的接口,为了保持接口不变及已有代码的功能,就对原有MqttCallback接口进行了继承扩展,内部实现检测到传入的callback也是MqttCallbackExtended 的实例,就会回调 connectComplete 接口了。
// If we are using the MqttCallbackExtended, set it on the
// connectActionListener
if (this.mqttCallback instanceof MqttCallbackExtended) {
   connectActionListener.setMqttCallbackExtended((MqttCallbackExtended) this.mqttCallback);
}

可以谓之为: “扩展模式”吧!

补充说明一点:MqttCallback 中的messageArrived回调是消息收到回调的缺省回调,如果subscribe(String topicFilter, int qos, IMqttMessageListener messageListener)指定了 IMqttMessageListener 会覆盖该回调,也即:使用IMqttMessageListener 回调,MqttCallback 中的messageArrived回调无响应了

/* (non-Javadoc)
 * @see org.eclipse.paho.client.mqttv3.IMqttClient#subscribe(java.lang.String, int)
 */
public void subscribe(String topicFilter, int qos, IMqttMessageListener messageListener) throws MqttException {
   this.subscribe(new String[] {topicFilter}, new int[] {qos}, new IMqttMessageListener[] {messageListener});
}

具体原因:详见代码。

org.eclipse.paho.client.mqttv3-1.2.0-sources.jar!\org\eclipse\paho\client\mqttv3\internal\CommsCallback.java

protected boolean deliverMessage(String topicName, int messageId, MqttMessage aMessage) throws Exception
{     
   boolean delivered = false;
   
   Enumeration keys = callbacks.keys();
   while (keys.hasMoreElements()) {
      String topicFilter = (String)keys.nextElement();
      if (MqttTopic.isMatched(topicFilter, topicName)) {
         aMessage.setId(messageId);
         ((IMqttMessageListener)(callbacks.get(topicFilter))).messageArrived(topicName, aMessage);
         delivered = true;
      }
   }
   
   /* if the message hasn't been delivered to a per subscription handler, give it to the default handler */
   if (mqttCallback != null && !delivered) {
      aMessage.setId(messageId);
      mqttCallback.messageArrived(topicName, aMessage);
      delivered = true;
   }
   
   return delivered;
}

OK。验证如下:

taskClient.getMqttClient().setCallback(new MqttCallbackExtended() {
    @Override
    public void connectComplete(boolean reconnect, String serverURI) {
        AlLog.getLogger().warn("TaskClient connectComplete reconnect={} serverURI={}", reconnect, serverURI);
    }

    @Override
    public void connectionLost(Throwable cause) {
        AlLog.getLogger().error("TaskClient connectionLost " + taskClient.isConnected() + " cause:", cause);

    }

    @Override
    public void messageArrived(String topic, MqttMessage message) throws Exception {
        AlLog.getLogger().debug("TaskClient messageArrived message:{}", message);
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken token) {
        AlLog.getLogger().debug("TaskClient deliveryComplete token:{}", token);
    }
});

日志:

02-28 14:45:09.668 E/29252.64,MQTT Ping: devXXX SubscribeTask$1.connectionLost.41: TaskClient connectionLost false cause:
02-28 14:45:10.738 W/29252.63,MQTT Call: devXXX SubscribeTask$1.connectComplete.63: TaskClient connectComplete reconnect=true serverURI=tcp://XXX.XXX.XXX.XXX:1883
02-28 14:45:26.514 W/29252.35,Timer-0 SubscribeTask$3.run.93: TimerTask taskClient isConnected true

OK。 just 必列...

 

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
MQTT客户无法连接MQTT服务器时,可能有多种原因导致。下面是一些常见的解决方法: 1. 检查网络连接:确保客户MQTT服务器之间的网络连接正常。可以使用ping命令或其他网络工具测试连接。 2. 检查服务器地址和口:确认客户代码中配置的MQTT服务器地址和口号是否正确。确保它们与实际的服务器配置相匹配。 3. 检查客户身份验证信息:如果MQTT服务器要求身份验证,确保客户代码中提供了正确的用户名和密码。 4. 检查TLS/SSL配置:如果MQTT服务器启用了TLS/SSL加密连接,确保客户代码中的TLS/SSL配置正确,并且证书文件可用。 5. 检查防火墙和网络代理:如果使用了防火墙或网络代理,确保它们允许MQTT流量通过。有时候需要在防火墙或代理服务器上进行配置。 6. 检查MQTT服务器状态:确认MQTT服务器正在运行,并且监听指定的口。可以查看服务器的日志文件或使用一些监控工具来确认服务状态。 7. 使用其他MQTT客户工具进行测试:尝试使用其他MQTT客户工具(如MQTT.fx、mosquitto_sub/mosquitto_pub等)连接到同一台MQTT服务器,以确定是客户代码还是服务器配置的问题。 如果以上方法都无法解决问题,可以进一步查看MQTT客户的日志或错误信息,以及MQTT服务器的日志,以获取更多的调试信息。另外,也可以参考MQTT协议的规范文档或向相关技术支持寻求帮助。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

行知致简

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值