Я реализую функцию, которая позволит клиенту mqtt подключаться к другому брокеру во время выполнения и использовать имя пользователя и пароль, предоставленные пользователем.
- Я использую статическую сборку Qt 5.11.2 с компилятором MSVC 15.0.
- Это клиент для Windows, у которого mosquitto_loop_forever () в цикле, выполняемом в отдельном потоке (используя WinAPICreateThread ()).
- Я использовал mosquitto 1.5.4 для своей программы.
- Когда предполагается подключение к другому брокеру, я вызываю mosquitto_disconnect (), а затем снова mosquitto_connect ()с новыми данными, и я снова вызываю mosquitto_username_pw_set () для установки нового имени пользователя и пароля перед mosquitto_connect ().
- Я пока не использую SSL / TLS, я подключаюсь через стандартный порт 1883, и удаленный брокер принимает соединения оттам.
Проблема возникает, когда я хочу, чтобы мой клиент переключил свое соединение с другим брокером в моей локальной сети. Это попадает в петлю переподключения. По-видимому, он отправляет сообщение CONNECT дважды, что, как я изначально подозревал, приводит к дублированию идентификатора и, следовательно, CONNACK (5) на удаленном посреднике, но это оказалось чем-то другим.
Я выяснил, удалив строки, которые устанавливаютпараметры экземпляра mosquitto, это то, что mosquitto_username_pw_set () вызывает отказ от брокера - CONNACK (5), но когда эта функция удалена, CONNECT по-прежнему происходит дважды, а соединение просто нормально - CONNACK (0).
ВопросВот почему удаление этой конкретной функции позволяет соединению работать нормально и почему CONNECT отправляется вообще дважды?
Вот что я пробовал:
- Я дважды проверил, могут ли мои идентификаторыбыть жестко закодированным в любом месте, это был совет, который я часто видел на стеке и где угодно. Идентификаторы клиента не жестко закодированы.
- I проверено , если mosquitto_username_pw_set () возвращает MOSQ_ERR_SUCCESS, и это происходит.
- Я попытался перейти на mosquitto 1.6.7. Такое же поведение происходит.
- Я проверил, были ли в моих темах, именах пользователей и паролях завершающие символы в конце. У них их не было.
- Я попытался уничтожить экземпляр mosquitto и снова вызвать mosquitto_new () перед подключением. Не помогло.
- Итак, я сделал минимальный пример, в котором нет зависимостей Qt, он переключается между 1 и 2 и воспроизводит проблему, поэтому я могу надеяться, что ее можно будет легко определить, удалив функции, которые устанавливают параметрыпо одному. Поведение все еще происходит, так что, вероятно, это не какая-то специфика Qt.
Когда я полностью удаляю mosquitto_username_pw_set () из кода, клиент подключается очень хорошо (CONNACK (0)), но CONNECT равен все еще уходит дважды , но без CONNACK (5).
Я не уверен, почему это происходит.
Вот некоторый код:
Функция потока:
DWORD WINAPI MosqThread(LPVOID lpParam)
{
while (1)
{
mosquitto_loop_forever(g_mosq_ext, 1000, 1);
}
return 0;
}
Инициализация Mosquitto:
mosquitto_lib_init();
bool clean_session = true;
g_mosq_ext = mosquitto_new(NULL, clean_session, NULL);
Часть кода, в которой проблема возникает с этой очень специфической функцией mosquitto_username_pw_set ().
(подключение к localhost в основном идентично, как в "num == 2" для адреса локальной сети)
while(true)
{
num = getchar();
if(num == '1')
{
//connect to localhost
}
if(num == '2')
{
int rc;
do {
mosquitto_disconnect(g_mosq_ext);
//Removing this function from everywhere in the code
//makes client connect to broker just fine
//Otherwise, no
mosquitto_username_pw_set(g_mosq_ext, "guest", "guest");
mosquitto_log_callback_set(g_mosq_ext,log_callback);
mosquitto_connect_callback_set(g_mosq_ext,connect_callback);
mosquitto_disconnect_callback_set(g_mosq_ext,disconnect_callback);
rc = mosquitto_connect(g_mosq_ext, "192.168.1.75", 1883, true);
printf("[%s] 192.168.1.75: %s rc=%d\n",
__FUNCTION__,
mosquitto_strerror(rc),
rc);
printf("sleep 1 sec \n");
_sleep(1000);
printf("sleep done \n");
} while (rc != MOSQ_ERR_SUCCESS);
//Start thread, calls CreateThread() in itself
thread();
}
}
Поскольку я тестировал этот минимальный пример, я собрал несколько журналов.
Обратные вызовы журналов показали мне это:
1
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending CONNECT
[main] localhost: No error. rc=0
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received CONNACK (0)
[connect_callback] Connection Accepted. 0
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending PINGREQ
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received PINGRESP
2
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending DISCONNECT
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending CONNECT
[main] 192.168.1.75: No error. rc=0
sleep 1 sec
sleep done
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending CONNECT
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received CONNACK (5)
[connect_callback] Connection Refused: not authorised. 5
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending CONNECT
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received CONNACK (5)
[connect_callback] Connection Refused: not authorised. 5
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending CONNECT
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received CONNACK (5)
[connect_callback] Connection Refused: not authorised. 5
1
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending CONNECT
[main] localhost: No error. rc=0
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending CONNECT
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received CONNACK (0)
[connect_callback] Connection Accepted. 0
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending CONNECT
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received CONNACK (0)
[connect_callback] Connection Accepted. 0
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending PINGREQ
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending PINGREQ
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k sending PINGREQ
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received PINGRESP
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received PINGRESP
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received PINGRESP
[log_callback] 4191392.004 Client mosq-11EwIEknLGlr2Joo3k received PINGRESP
Существует дубликат CONNECT, которыйЯ подозреваю, что это может быть проблемой.
И когда я попытался удалить mosquitto_username_pw_set (), чтобы увидеть, где он меня находит:
1
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH sending CONNECT
[main] localhost: No error. rc=0
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH received CONNACK (0)
[connect_callback] Connection Accepted. 0
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH sending PINGREQ
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH received PINGRESP
2
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH sending DISCONNECT
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH sending CONNECT
[main] 192.168.1.75: No error. rc=0
sleep 1 sec
sleep done
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH sending CONNECT
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH received CONNACK (0)
[connect_callback] Connection Accepted. 0
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH sending PINGREQ
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH sending PINGREQ
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH received PINGRESP
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH received PINGRESP
[log_callback] 3863712.003 Client mosq-qZDF50s4TWJEM7LSHH received PINGRESP
CONNECT все еще происходит дважды, но посредник не отказывает в соединенияхпотому что mosquitto_username_pw_set () отсутствует.
Я ожидал, что смогу правильно подключиться к другому брокеру с помощью mosquitto_username_pw_set (), но я как-то получаю CONNECT дважды, а затемCONNACK (5), когда по всем учетным записям это не должно происходить, и в то же время, когда этой функции нет, клиент подключается просто отлично, даже если CONNECT все еще отправляется дважды с одного и того же идентификатора.
Это mosquitto_loop_forever () пытается переподключиться и затем мешает с синхронизацией?
Есть ли что-то, что делает mosquitto_username_pw_set ()?
Это на самом деле конфигурация брокера, которую я долженотметьте вместо этого?
Есть еще идеи?