11

Вопрос по android – Как отправить пинг с помощью Eclipse Paho MQTT клиент?

Мы только начали создавать нашу собственную систему push-уведомлений (из-за требований клиента) для Android и нашли Eclipse Paho (http://www.eclipse.org/paho/). Излишне говорить, что этот проект действительно захватывающий.

Проблема с Android состоит в том, что, если процессор находится в состоянии сна, клиент MQTT может не получить возможность отправлять эхо-запрос с установленным интервалом. Обходной путь использует AlarmManager, чтобы разбудить его и выполнить работу. Документация Android гласит:

The Alarm Manager holds a CPU wake lock as long as the alarm receiver's onReceive() method is executing. This guarantees that the phone will not sleep until you have finished handling the broadcast. Once onReceive() returns, the Alarm Manager releases this wake lock. This means that the phone will in some cases sleep as soon as your onReceive() method completes.

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

Мне нужно быть уверенным, что я могу отправить команду ping в этом методе onReceive (), пока у процессора есть PARTIAL_WAKE_LOCK, поэтому я искал способ вручную отправить ping на сервер, но, похоже, клиент не предоставляет такой метод. Я что-то пропустил? Или какой здесь обходной путь, кроме публикации моего собственного сообщения "ping"? Я хочу избежать этого из-за:

  1. Larger overhead
  2. We'll ensure that Android clients are subscriber only, may be with Mosquitto's ACL. They will not be allowed to publish messages.
  • Да, сейчас это лучший вариант, так как мне не нужен сервер для запоминания сессий при переподключении. Спасибо за ваше время!

    от Mehdi
  • Еще одна вещь на заметку: Eclipse Paho имеет класс персистентности внутренней памятиorg.eclipse.paho.client.mqttv3.internal.MemoryPersistence Я использую это, чтобы избежать неприятностей, которые вы упомянули.

    от Mehdi
  • Спасибо! Причина, по которой клиенты не публикуются, заключается в том, чтоmax length сообщений, поддерживаемых MQTT / Mosquitto, слишком много, по ссылке ~ 260 МБ. Как вы думаете, это ставит под угрозу сервер? Поскольку бесплатные брокеры (Mosquitto / RSMB) не поддерживают SSL, простая аутентификация на основе имени пользователя и пароля не казалась мне достаточно безопасной, поэтому я хотел запретить публиковать доступ кому-либо, кроме самого сервера, на котором работает Man-in-the -средняя атака невозможна. Я не эксперт по безопасности, это всего лишь предположение.

    от Mehdi
  • чтобы избежать изменения классаorg.eclipse.paho.client.mqttv3.MqttAsyncClient (шаг 1) вы можете создать класс MqttClient2 в пакете с именемorg.eclipse.paho.client.mqttv3 (обрабатывается на шаге 2 мгновенно)

    от
  • Это работает только до mqtt-client-0.4.0. В поле mqtt-client-0.4.1-SNAPSHOT aClient класса MqttClient был изменен на private и protected, поэтому он недоступен в дочернем классе. Есть ли другое решение, чтобы оно работало для o.4.1-SNAPSHOT и позже?

    от
  • Возможен ли второй подход с использованием сообщений QoS 1 или 2, отправленных с сервера? Или вам нужна чистая сессия = правда?

    от
  • Хм, крутой. Я предполагаю, что это зависит от того, насколько надежен брокер и сможет ли он справиться с тем, кто бомбардирует его сообщениями ~ 260 МБ, пытаясь затопить его; так как это единственная атака, я думаю, это оставит вас открытыми. Как вы говорите, простое имя пользователя и пароль не обеспечивают никакой защиты, поскольку их можно просто прослушать по проводам.

    от
  • Отличная идея. Спасибо!

    от
  • Благодарю за ваш ответ. Я видел ваш пост, прежде чем начать работу над ним, это отличный ресурс по теме, должен признать. Я думал о «расширении» Клиентская библиотека Paho, но, кажется, это невозможно (в хорошем смысле). Он хранит экземпляр класса ClientComms внутри частного поля, а объект ClientComms хранит в нем объект ClientState, также в частном поле. ClientState отвечает за управление эхо-запросами (запрос, ответ и время). В этом случае мне придется изменить ядро, сделав его беспорядочным :(

    от Mehdi
  • При этом вы заметили, что MqttService останавливается, если вы удаляете приложение из последних приложений? После этого сообщения не принимаются, и вы отключаетесь от брокера. Как (если у вас есть) вы решили эту проблему?

    от Muhamed Huseinbašić
  • 2

    Есть способ изменить код Paho и сделать пинг в любое время. Если мы ис

    пользуем тему публикации для поддержания активности, мы должны отправить на сервер не менее 7 или 8 байт. Да, 8 байтов - это еще не большие данные. Но сердцебиение MQTT составляет всего 2 байта. Мы потеряли лучшее преимущество MQTT.

    Посмотрите подробно на код paho, я изменяю его и пишу открытый метод с именем nnnn () в MQTTClient. Этот метод может отправить MqttPingReq на сервер. реализацию можно найти здесь ...https://github.com/chinesejie/paho-for-android

  • 2

    мое решение:

    (1) изменить:ClientComms comms; отprotected вpublic (в упаковкеorg.eclipse.paho.client.mqttv3)

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

    (2) определить новый класс: (производный от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();
    

    Надеюсь, это может быть полезным для вас.

  • 15

    Я работал с MQTT на Android

    и у меня возникла точно такая же проблема.

    Как говорит Дейл, в старой версии MQTT-клиента был явный метод ping (), но, к сожалению, теперь он скрыт.

    Простейший подход, который я использую, - это явная публикация 1-байтового сообщения в определенную тему для поддержки активности. Я не думаю, что это должно значительно увеличить накладные расходы вашего приложения, и, хотя я не знаком с ACL Mosquitto, я предполагаю, что вы могли бы заставить каждого клиента использовать один и тот же "keepalive". тема и просто предоставить доступ для записи всем. Это не должно влиять на безопасность, пока никто не может прочитать из темы.

    Альтернативный подход заключается в том, чтобы сервер отправлял клиенту (-ам) «keepalive». сообщение в QoS 1 или 2 (публикация / переход через одну тему для всех для эффективности), поскольку из-за потоков QoS это будет включать в себя отправку клиентом сообщения обратно на сервер под прикрытием; который будет служить keepalive. Это имеет преимущество в том, что ваши клиенты остаются только подписчиками; однако это несовместимо с «чистым сеансом = ложь»; (поскольку у вас будет большое количество сообщений, поставленных в очередь для доставки клиентам, которые какое-то время находятся в автономном режиме - без необходимости влияя на производительность при повторном подключении).

    К сожалению, это единственные два обходных пути, о которых я сейчас могу думать.

    Кроме того, если коротко, я столкнулся с рядом проблем, связанных с использованием MqttDefaultFilePersistence на Android, так что вы можете об этом знать. В частности, что касается блокировки файлов и проблем при повторном создании клиента. Чтобы обойти это, я создал реализацию MqttClientPersistence, построенную поверх базы данных SQLite, и это намного надежнее; Вы можете сделать то же самое.

  • 10

    Я сталкивался с этой проблемой

    когда писал приложения для MQTT для Android год или около того назад. Я написал об этом довольно подробно вhttp://dalelane.co.uk/blog/?p=1599 но вкратце да - я видел ту же проблему, которую вы описываете, когда процессор спит, когда клиент MQTT должен отправить ему пинг, тогда пинг никогда не отправляется.

    Разница в том, что я использовал для вас другую клиентскую библиотеку MQTT (это было до появления Paho), а в используемой мной клиентской библиотеке был метод ping (), который я мог вызвать. (Полный источник моей реализации находится по этой ссылке, и это решает эту проблему).

    Не можете ли вы расширить реализацию клиентской библиотеки Paho, включив в нее команду PING? Я полагаю, это должна быть небольшая модификация.