#mqtt #mosquitto #libmosquitto
Вопрос:
У меня есть эта программа, использующая библиотеку mosquitto MQTT:
/*
compile using:
$ gcc -o libmosq libmosq.c -lmosquitto
*/
#include <stdio.h>
#include <mosquitto.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
void connection_callback(struct mosquitto* mosq, void *obj, int rc)
{
if (rc) {
printf("connection error: %d (%s)n", rc, mosquitto_connack_string(rc));
}
else {
printf("connection successn");
}
}
void publish_callback(struct mosquitto* mosq, void *obj, int mid)
{
printf("this is the publish callbackn");
}
int main(int argc, char *argv[])
{
struct mosquitto *mosq = NULL;
mosquitto_lib_init();
mosq = mosquitto_new(NULL, true, NULL);
if(!mosq) {
fprintf(stderr, "Error: Out of memory.n");
exit(1);
}
mosquitto_connect_callback_set(mosq, connection_callback);
mosquitto_publish_callback_set(mosq, publish_callback);
mosquitto_username_pw_set(mosq, "user1", "passwd1");
int resultCode = mosquitto_connect(mosq, "localhost", 1883, 60);
if (resultCode != MOSQ_ERR_SUCCESS) {
fprintf(stderr, "error calling mosquitto_connectn");
exit(1);
}
int loop = mosquitto_loop_start(mosq);
if(loop != MOSQ_ERR_SUCCESS){
fprintf(stderr, "Unable to start loop: %in", loop);
exit(1);
}
char topic[] = "/testtopic";
char msg[] = "foobar";
int publish = mosquitto_publish(mosq, NULL, topic, (int) strlen(msg), msg, 0, false);
if(publish != MOSQ_ERR_SUCCESS){
fprintf(stderr, "Unable to publish: %in", publish);
exit(1);
}
// hang until control C is done
sleep(1000000);
}
По сути, он подключается к брокеру MQTT и публикует на нем сообщение.
Если я запущу программу, я получу следующий результат:
this is the publish callback
connection success
Это означает, что обратный вызов публикации вызывается до обратного вызова соединения, что, с моей точки зрения, противоречит здравому смыслу (поскольку порядок событий противоположен: сначала происходит соединение, затем сообщение о публикации отправляется из моей программы брокеру MQTT).
Как это возможно? Почему происходит такое противоречивое поведение? Спасибо!
Комментарии:
1. Подсказка: Это публикация QOS 0….
2. Спасибо за отзыв! Если я изменю QOS на 1, я получу сообщение в обратном порядке (т. Е. Сначала
connection success
this is the publish callback
).3. Однако я не уверен, что полностью понимаю, как это работает… насколько я понимаю, обратный вызов соединения вызывается при получении соединения, что эффективно подтверждает соединение. Может ли клиент MQTT публиковать сообщения еще до получения соединения?
Ответ №1:
Важно понимать, что mosquitto_connect()
, хотя блокировка не блокирует весь процесс подключения, она блокируется только до тех пор, пока пакет ПОДКЛЮЧЕНИЯ не будет отправлен, она не ожидает возврата пакета ПОДКЛЮЧЕНИЯ, следовательно on_connect
, обратного вызова.
Таким образом, вполне возможно, что весь код после вызова mosquitto_connect()
будет выполнен вплоть до вызова на публикацию, включая вызов на публикацию, до получения этого пакета подключения. И учитывая on_publish
, что обратный вызов для сообщения QOS 0 будет вызван, как только будет отправлен пакет ПУБЛИКАЦИИ (или, возможно, даже когда он будет добавлен в исходящую очередь), поскольку подтверждения нет, это также может произойти до получения СОЕДИНЕНИЯ.
Если вы хотите сделать это правильно, то весь код публикации должен быть перемещен в on_connect
обратный вызов (или закрыт по флагу, установленному в этом обратном вызове).
P.S. ваша тема ДЕЙСТВИТЕЛЬНО не должна начинаться с ведущего /
. Хотя технически это спецификация, она просто откладывает проблемы на потом, поскольку добавляет null
запись в начало дерева тем, которая нарушит такие вещи, как общие подписки, когда вы до них доберетесь.