繁体   English   中英

如何使用 Eclipse Paho MQTT 客户端发送 ping?

[英]How to send ping using Eclipse Paho MQTT client?

我们刚刚开始为 Android 构建我们自己的推送通知系统(由于客户的要求),并找到了 Eclipse Paho ( http://www.eclipse.org/paho/ )。 不用说,这个项目真的很令人兴奋。

Android 的问题是,如果 CPU 处于睡眠状态 state,MQTT 客户端可能无法在其设置的时间间隔内发送 ping。 解决方法是使用 AlarmManager 唤醒它并完成工作。 Android 文档说:

只要警报接收器的 onReceive() 方法正在执行,警报管理器就会持有 CPU 唤醒锁。 这保证了在您处理完广播之前手机不会休眠。 一旦 onReceive() 返回,Alarm Manager 释放这个唤醒锁。 这意味着手机在某些情况下会在您的 onReceive() 方法完成后立即休眠。

http://developer.android.com/reference/android/app/AlarmManager.html

我需要确保在 CPU 具有 PARTIAL_WAKE_LOCK 时我可以在该 onReceive() 方法中发送 ping 命令,因此我正在寻找一种手动向服务器发送 ping 的方法,但客户端似乎没有公开任何此类方法。 我错过了什么吗? 或者,除了发布我自己的“ping 消息”之外,这里的解决方法是什么? 我想避免这种情况,因为:

  1. 更大的开销
  2. 我们将确保 Android 客户端仅为订阅者,可能使用 Mosquitto 的 ACL。 他们将不允许发布消息。

我一直在 Android 上使用 MQTT 做一些工作,我遇到了完全相同的问题。

正如 Dale 所说,旧版本的 MQTT 客户端曾经有一个显式的 ping() 方法,但不幸的是,它现在被隐藏了。

最简单的方法,也是我使用的方法,是向特定主题显式发布一条 1 字节的消息,作为保活。 我认为这不会增加应用程序的开销,虽然我不熟悉 Mosquitto 的 ACL,但我假设您可以让每个客户端使用相同的“keepalive”主题并只提供对所有客户端的写访问权限。 只要没有人可以阅读该主题,这就不会影响安全性。

另一种方法是让服务器以 QoS 1 或 2 向客户端发送“保持活动”消息(通过单个主题发布/订阅以提高效率),因为由于 QoS 流,这将涉及客户端在幕后向服务器发送回消息; 这将作为保活。 这样做的好处是让您的客户仅作为订户; 然而,它与“clean session = false”不兼容(因为您会有大量消息排队等待发送给离线一段时间的客户端 - 不必要地影响重新连接时的性能)。

不幸的是,这些是我目前能想到的仅有的两种解决方法。


此外,顺便说一句,我在 Android 上使用 MqttDefaultFilePersistence 时遇到了很多问题,因此您可能需要了解这一点。 特别是与重新实例化客户端时的文件锁定和问题有关。 为了解决这个问题,我创建了一个建立在 SQLite 数据库之上的 MqttClientPersistence 实现,它更加健壮; 你可能想做同样的事情。

大约一年前,我在为 Android 编写 MQTT 应用程序时遇到了这个问题。 我已经在http://dalelane.co.uk/blog/?p=1599上详细介绍了它,但简而言之,是的 - 我看到了与您描述的相同问题,如果 MQTT 客户端时 CPU 处于睡眠状态应该发送它的 ping,然后 ping 永远不会被发送。

不同之处在于,我使用的是与您不同的 MQTT 客户端库(这是在 Paho 时代之前),而我使用的客户端库确实有一个我可以调用的 ping() 方法。 (我的实现的完整源代码在那个链接上,它确实解决了这个问题)。

您不能扩展 Paho 客户端库的实现以包含 PING 命令吗? 我认为这应该是一个相当小的修改。

有办法修改paho代码,随时ping。 如果我们使用发布主题来保持活动状态,我们必须至少向服务器发送 7 或 8 个字节。 是的,8 字节仍然不是大数据。 但是MQTT的心跳只有2bytes。 我们失去了 MQTT 的最佳优势。

深入查看paho代码,我修改了它,在MQTTClient中写了一个名为nnnn()的公共方法。 此方法可以将 MqttPingReq 发送到服务器。 实现可以在这里找到... https://github.com/chinesejie/paho-for-android

我的解决方案:

(1) 修改: ClientComms comms; protectedpublic (在 package org.eclipse.paho.client.mqttv3

public class MqttAsyncClient implements IMqttAsyncClient { // DestinationProvider {
    //...
    public ClientComms comms;  // Add by Ben for pingreq*
    //...
}

(2) 定义新的 class:(派生自MqttClient

public class MqttClient2 extends MqttClient {

    public MqttClient2(String serverURI, String clientId,   MqttClientPersistence persistence) throws MqttException {
        super(serverURI, clientId, persistence);
    }

    public void pingreq()  throws MqttException {

        MqttDeliveryToken token = new MqttDeliveryToken(getClientId());
        MqttPingReq pingMsg = new MqttPingReq();
        aClient.comms.sendNoWait(pingMsg, token);

    }
}

(3) 随时随地,您可以:

MqttClient2 mClient = new MqttClient2(url, mDeviceId, mDataStore);
mClient.pingreq();

希望这对您有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM