Протокол MQTT -- ПОДКЛЮЧИТЬСЯ И ПОДКЛЮЧИТЬСЯ

Интернет вещей

Обзор

Сегодня я узнаю о подключении к протоколу MQTT.Подключение является очень важной частью, поскольку оно является основой для связи между клиентом и MQTT-брокером и предоставляет множество полезных функций, которые можно использовать во многих сценариях. .

Теорию лучше совмещать с практикой, а то боюсь, что друзья уснут после просмотра. ~~~

Как упоминалось ранее, MQTT — это протокол передачи сообщений, основанный на публикации и подписке, поэтому клиент публикации MQTT может публиковать сообщения одному или нескольким клиентам-подписчикам. Эта модель очень похожа на теле- или радиопередачи, когда радиостанции выпускают программы, а миллионы домохозяйств принимают программы. Все сообщения отправляются брокеру MQTT, который затем пересылает сообщения своим подписчикам. В ходе этого процесса следует обратить внимание на следующие моменты:

  • Все клиенты имеют уникальный идентификатор, этот идентификатор является просто токеном, а не адресом клиента. Когда издатель публикует сообщение, он может отправить его только в определенную тему, но не на определенный адрес или идентификатор.
  • Идентификатор клиента не может повторяться. Если клиент-клиент A подключен к MQTT-брокеру, а другой клиент-клиент B подключается к MQTT-брокеру позже, MQTT-брокер отключит клиента A в это время. Поскольку клиент MQTT имеет функцию автоматического подключения, после отключения клиента A он пытается повторно подключиться к MQTT Broker.В это время клиент B будет снова отключен, а затем снова подключится клиент B, а затем два клиента войдут бесконечный цикл отключение-подключение-отключение.
  • Брокер MQTT отвечает за получение сообщений, их фильтрацию и пересылку клиентам, подписавшимся на соответствующие темы.
  • Издатель и подписчик не связаны напрямую. Все они подключаются только к брокеру MQTT.
  • Клиенты могут отправлять, так и получать сообщения.
  • Обычно MQTT Broker не хранит сообщения.

Теперь у вас должно быть более четкое представление о MQTT Client и Broker. Давайте обсудим формат MQTT Connect.


CONNECT

Fixed Header

Фиксированный заголовок MQTT содержит первый байт и переменную длину. Старшие 4 бита (бит7~бит4) первого байта используются для указания типа сообщения, а 1 указывает на соединение. Все остальные байты маркера (bit3~bit0) равны 0, как показано в следующей таблице.

Bit 7 6 5 4 3 2 1 0
Byte 1 0 0 0 1 0 0 0 0
Byte 2... Remaining Length
Variable Header

В сообщении Connect заголовок переменной содержит 10 байтов, как показано в следующей таблице:

Byte Description bit7 bit6 bit5 bi4 bit3 bit2 bit1 bit0
Byte 1 Length MSB (0) 0 0 0 0 0 0 0 0
Byte 2 Length LSB (4) 0 0 0 0 0 1 0 0
Byte 3 'M' 0 1 0 0 1 1 0 1
Byte 4 'Q' 0 1 0 1 0 0 0 1
Byte 5 'T' 0 1 0 1 0 1 0 0
Byte 6 'T' 0 1 0 1 0 1 0 0
Byte 7 Level(4) 0 0 0 0 0 1 0 0
Byte 8 Connect Flag User Name Password Will Retain Will QoS Will QoS Will Flag Clean Session Reserved
Byte 9 Keep Alive MSB 0 0 0 0 0 0 0 0
Byte 10 Keep Alive MSB 0 1 1 0 0 0 0 0

Содержимое заголовка переменной включает имя протокола, уровень протокола, флаги подключения и время поддержания активности. Соответственно следующие:

Protocol Name:Байты 1-6, эта часть содержимого является фиксированной, где байт 1 и байт 2 представляют длину имени протокола, а его содержимое равно 0x04. Байт 3 — байт 6 представляет собой кодировку UTF-8 имени протокола «MQTT».

Protocol Level:Байт 7, указывающий уровень протокола, уровень протокола версии протокола MQTT 3.1.1 равен 4.

Connect Flag:Байт 8, флаг соединения, каждый бит представляет собой флаг, бит 0 является зарезервированным флагом. От бита 1 до бита 7 они представляют чистую сессию, отметку воли и т. д. соответственно. Эти флаги определяют, содержит ли полезная нагрузка соответствующую информацию. Например, если значения Bit7 и Bit6 равны 1, это означает, что имя пользователя и пароль включены в полезную нагрузку этого соединения. Функция каждого маркера будет описана позже.

Keep Alive:Байт 9 и байт 10, интервал сердцебиения между клиентом и сервером, старший байт идет первым, а младший байт последним. Единица S, по умолчанию 60S. Что следует отметить в Keep Alive:

  • Когда нет передачи сообщений между клиентом и сервером, клиент будет отправлять пакеты данных PINGREQ брокеру MQTT каждые 60 секунд (значение поддержания активности). Сервер должен ответить на пакет данных PINGRESP.
  • Если клиент не получает пакет PINGRESP после отправки пакета PINGREQ в течение определенного периода времени, клиент отключается.
  • Если значение Keep Alive установлено больше 0 (при условии, что 60 с), при отсутствии взаимодействия с данными, если сервер не получает пакет PINGREQ после более чем 1,5-кратного времени Keep Alive (90 с), сервер отключиться от текущего клиента.завершить соединение.
  • Keep Alive можно установить на 0, тогда клиент не будет отправлять пакет PINGREQ, а сервер не отключит клиента, потому что он не получает PINGREQ.

Давайте протестируем Keep Alive и посмотрим на пакеты PINGREQ и PINGRESP. Введите следующую команду в терминал командной строки, и вы получите соответствующий результат:

$ mosquitto_sub -t topic001 -k 5 -d
Client mosqsub|16532-SCNWCL012 sending CONNECT
Client mosqsub|16532-SCNWCL012 received CONNACK (0)
Client mosqsub|16532-SCNWCL012 sending SUBSCRIBE (Mid: 1, Topic: topic001, QoS: 0)
Client mosqsub|16532-SCNWCL012 received SUBACK
Subscribed (mid: 1): 0
Client mosqsub|16532-SCNWCL012 sending PINGREQ
Client mosqsub|16532-SCNWCL012 received PINGRESP
Client mosqsub|16532-SCNWCL012 sending PINGREQ
Client mosqsub|16532-SCNWCL012 received PINGRESP
Client mosqsub|16532-SCNWCL012 sending PINGREQ
Client mosqsub|16532-SCNWCL012 received PINGRESP

В приведенной выше команде -t тема 001 означает подписаться на тему темы 001. Используйте -k 5, чтобы установить интервал поддержания активности равным 5 с, и -d, чтобы включить режим отладки. Из вывода видно, что каждые 5 секунд клиент отправляет PINGREQ и получает PINGRESP, возвращаемый с сервера.

Connect Flag

Поскольку Connect Flag содержит много контента, он представлен в отдельном разделе.

Reserved

Bit0 8-го байта. Зарезервированный бит, должен быть равен 0.

Clean Session

Бит 1 8-го байта используется для указания необходимости очистки сеанса, если значение равно 0, то это означает сохранение сеанса, а если равно 1, то это означает, что сеанс необходимо очистить.

Клиенты и брокеры могут хранить некоторую информацию о состоянии сеанса для надежной передачи сообщений. Мы знаем, что MQTT обеспечивает надежную передачу сообщений, определяя уровень QoS, поэтому самое важное в информации о состоянии сеанса — это состояние сообщения QoS. Возьмем брокера в качестве примера, для сообщений с QoS 1 или 2, если брокер не может успешно доставить сообщение клиенту А, статус сообщения будет сохранен.Когда клиент А повторно подключится в следующий раз, сервер повторно доставит сообщение, которое ранее не удалось доставить. в соответствии с состоянием сеанса.

Таким образом, если клиент публикует или подписывается на тему и устанавливает QoS> 0, то чистое сеанс должен быть установлен на 0.

Will Flag

Бит 2 8-го байта используется для обозначения того, следует ли отправлять сообщение о последнем желании.

Последнее сообщение-желание означает, что когда клиент аварийно отключается, клиент хочет отправить сообщение в указанную тему, чтобы уведомить другую сторону об отключении. Одним из сценариев применения последнего сообщения о желании является напоминание об отключении устройства.Когда устройство отключено, абонент (обычно фоновый сервер) знает, что устройство было отключено.

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

Если для параметра Will Flag установлено значение 1, то должны быть Will Topic и Will Message, а также будут прочитаны Will QoS и Will Retain. Последнее сообщение запроса также может быть установлено на QoS, что может гарантировать надежную доставку последнего сообщения запроса.

Итак, при каких обстоятельствах Брокер отправляет Will Message? Брокер отправит умирающее сообщение, когда произойдет любое из следующих событий.

  • сетевая аномалия
  • Сервер не получает PINGREQ после тайм-аута Keep Alive
  • Клиент не отправил DISCONNECT перед закрытием соединения
  • Сервер закрыл клиентское соединение из-за ошибки протокола

Следует отметить, что если клиент нормально закрывает соединение и отправляет DISCONNECT перед закрытием соединения, последнее сообщение не будет отправлено. Когда клиент отправляет запрос DISCONNECT, последнее сообщение о желании будет удалено Брокером.

Will QoS

Бит 3 и бит 4 8-го байта используются для установки QoS последнего сообщения о желании.Поскольку QoS имеет 3 значения, 0, 1 и 2, оно представлено двумя битами, старший разряд находится впереди, а младший разряд сзади.

Will Retain

Бит 5 8-го байта используется для обозначения того, следует ли сохранять последнее сообщение о желании.

Также полезен флаг Will Retain, если он установлен в 1, то при отключении клиента все новые подписчики будут получать сообщение о последнем желании при подписке на Will Topic. QoS > 0 могут получить только подписчики, которые ранее подписывались на газету, а Will Retain может гарантировать, что новые подписчики также получат сообщение.

User Name Flag

Используется для отметки того, включена ли информация об имени пользователя в полезную нагрузку. Если установлено значение 1, полезная нагрузка должна содержать информацию об имени пользователя.

Password Flag

Используется, чтобы отметить, содержит ли полезная нагрузка информацию о пароле. Если установлено значение 1, полезная нагрузка должна содержать информацию о пароле. Следует отметить, что если флаг имени пользователя установлен на 0, флаг пароля должен быть установлен на 0. Но он может содержать только имя пользователя, а не пароль, поэтому, когда флаг имени пользователя установлен на 1, флаг пароля также может быть установлен на 0.

Keep Alive

9-й и 10-й байты в заголовке переменной используются для указания времени поддержания активности. Это время — время пульса MQTT, единица измерения — секунды, а значение по умолчанию — 60 с. Когда между клиентом и брокером нет обмена данными, клиент должен отправить PINGREQ брокеру, а брокер отвечает на PINGRESP, чтобы определить, находится ли клиент в сети. Есть несколько замечаний по Keep Alive:

  • Клиент отвечает за отправку пульса PINGREQ, а сервер отвечает на PINGRESP только при получении пульса.
  • После того, как клиент отправит PINGREQ в течение определенного периода времени и не получит ответа, клиент закроет соединение.
  • После 1,5-кратного Keep Alive сервер не получает никаких данных от клиента, в том числе PINGREQ, а также закрывает соединение.
  • Keep Alive можно установить на 0, что означает, что механизм пульса не включен, тогда клиент и сервер не закроют соединение, потому что они не получили пульс или ответ.
Пример

Давайте рассмотрим пример переменного заголовка сообщения CONNECT, чтобы углубить наше понимание.

описывать 7 6 5 4 3 2 1 0
Ассоциация обсуждение Добрый тип
Байт 1. Тип длина высокая (0) 0 0 0 0 0 0 0 0
байт 2 Тип Длина Низкий (4) 0 0 0 0 0 1 0 0
байт 3 'M' 0 1 0 0 1 1 0 1
байт 4 'Q' 0 1 0 1 0 0 0 1
байт 5 'T' 0 1 0 1 0 1 0 0
байт 6 'T' 0 1 0 1 0 1 0 0
Ассоциация обсуждение Ждать сорт
слово 7 Level (4)
четное ловить отметка запомнить
байт 8 см. примечания 1 1 0 0 1 1 0 0
Keep Alive
байт 9 Держите в живых высокий 0 0 0 0 0 0 0 0
байт 10 Держите жизнь на низком уровне 0 0 0 0 1 0 1 0

Приведенный выше байт 8 представляет собой флаг имени пользователя (1), флаг пароля (1), будет сохранен (0), будет сохранен QoS (01), будет отмечен (1), чистый сеанс (1), зарезервирован (0).

Payload

После введения переменных заголовков давайте посмотрим на тело сообщения.

Протокол CONNECT содержит тело сообщения, содержимое которого — идентификатор клиента/[тема сообщения]/[сообщение сообщения]/[имя пользователя]/[пароль] соответственно.

Порядок вышеуказанных типов изменить нельзя. За исключением идентификатора клиента, другое содержимое является необязательным. Только когда соответствующее значение флага подключения равно 1, соответствующее содержимое включается в полезную нагрузку. Например, Will Topic и Will Message появятся в полезной нагрузке только тогда, когда флаг Will в части CONNECT Flag заголовка переменной равен 1.

Для содержимого во всех полезных нагрузках первые две цифры представляют собой длину, за которой следует содержимое данных. Мы проверим это позже, перехватив пакеты от Wire Shark.

Client Id

Идентификатор клиента – это уникальный идентификатор клиента. Этот идентификатор нельзя повторять. Если два клиента используют один и тот же идентификатор, они будут пинать друг друга. Если ваш клиент продолжает отключаться-подключаться-отключаться. Идентификатор повторяется. Что касается идентификатора клиента, обратите внимание на следующее:

  • Идентификатор клиента должен быть уникальным, предпочтительно осмысленным и читаемым. Например, наша компания использует _ в качестве идентификатора клиента. Как упоминалось ранее, хотя невозможно отправить сообщение непосредственно на идентификатор клиента, идентификатор клиента все еще полезен при устранении неполадок. Например, инструмент управления фоном EMQX может напрямую оценить, является ли клиент внутри в соответствии с идентификатором клиента и отслеживать все сообщения, отправленные и полученные определенным идентификатором клиента. Это полезно для онлайн устранения неполадок.
  • Идентификатор клиента может быть пустым.Если он пуст, сервер автоматически присвоит идентификатор, и затем назначенный идентификатор будет использоваться до отключения сети. Однако в производственной среде это не рекомендуется.
  • Идентификатор клиента связан с сеансом, поэтому, если вы используете QoS > 0 в своем проекте, вы не можете использовать случайный идентификатор клиента.
Will Topic & Will Message

Когда для флага завещания установлено значение 1, полезная нагрузка содержит тему завещания и сообщение завещания. Will Topic и Will Message уже говорили об этом, поэтому я не буду повторять их здесь.

User Name & Password

Если для этих двух флагов подключения установлено значение 1, полезная нагрузка содержит имя пользователя и пароль. Клиент может быть аутентифицирован и авторизован с помощью имени пользователя и пароля. Аутентификация может решить, разрешать ли клиентам подключаться, а авторизация может запретить клиентам доступ к определенным ресурсам (например, темам). Это относится к содержанию управления клиентами в Broker, которое мы представим позже.


CONNACK

После того, как клиент отправляет сообщение CONNECT, сервер должен ответить сообщением CONNACK. Если клиент отправляет CONNECT Брокеру и не получает CONNACK в течение определенного периода времени, клиенту необходимо закрыть текущее соединение.

Fixed Header

Фиксированный заголовок CONNACK выглядит следующим образом:

Bit 7 6 5 4 3 2 1 0
Byte 1 0 0 1 0 0 0 0 0
Byte 2 0 0 0 0 0 0 1 0

Еще раз вспомним формат фиксированного заголовка. Верхние 4 бита первого байта указывают тип протокола, 2 — CONNACK, младшие 4 бита — флаговые биты некоторых протоколов. Для CONNACK это зарезервированное поле.

Задняя часть фиксированного заголовка — это оставшаяся длина, протокол CONNACK, а длина его содержимого равна 2, что представлено одним байтом.

Variable Header

Заголовок переменной состоит из двух байтов и имеет следующий формат:

Bit 7 6 5 4 3 2 1 0
Byte 1 0 0 0 0 0 0 0 X
Byte 2 X X X X X X X X

Первые байты Bit7-Bit1 являются зарезервированными битами, а бит 0 используется для представления присутствия сеанса.

Второй байт — это код возврата. Мы вводим их отдельно.

Session Present

Наличие сеанса используется для указания, есть ли состояние сеанса на сервере. Как упоминалось ранее, когда для параметра «Очистка сеанса» установлено значение 0, сервер сохранит некоторый статус сеанса.Когда клиент повторно подключается, сервер будет судить о наличии статуса сеанса на основе идентификатора клиента.Если он существует, значение равно 1, иначе 0. Есть две вещи, которые следует отметить в отношении Session Present:

  • Когда клиент инициирует соединение и устанавливает для Чистого сеанса значение 1, Присутствующий сеанс всегда равен 0, независимо от того, имеет ли сервер состояние сеанса.

  • Если Код возврата, возвращенный Брокером, не равен 0, то Наличие Сессии должно быть равно 0.

Return Code

Второй байт заголовка переменной CONNACK представляет код возврата, который указывает статус возврата соединения. 0 означает успех, другие числа означают исключение, список кодов возврата выглядит следующим образом:

стоимость описывать
0X00 обычный
0X01 Сервер не поддерживает текущую версию протокола протокола
0X02 Соединение отказано, идентификатор клиента не имеет разрешения на подключение
0X03 Отклоняет соединение, сервер недоступен
0X04 Отказ в соединении, неверное имя пользователя и пароль
0X05 Отказ в соединении, нет авторизации
0X06-0XFF резерв

Разница между 0X02 и 0X05 выше: 0X02 — отказ аутентификации в соединении, 0X05 — сбой проверки авторизации и отказ в соединении.

Payload

CONNACK не имеет полезной нагрузки.


тестовое задание

Рассказывая так много, мы теперь вызываем тест пакета, проверяем содержимое, о котором мы сказали выше.

  1. Откройте Wire Shark, отслеживайте локальную сетевую карту обратной связи и введите tcp.port==1883 в качестве условия фильтра.

  2. Откройте терминал и введите следующую команду, чтобы отправить сообщение.

    mosquitto_pub -d -t topic1 --will-qos 2 --will-topic "will_topic" --will-payload "I'm offline!" -u "zengbiaobiao" -P "password" -m "Hello MQTT"
    
  3. Вернитесь в Wire Shark и просмотрите пакет CONNECT, как показано ниже.

mqtt-connect

Когда мы смотрим на протокол CONNECT, мы видим его подробное содержание данных,

Первая область показывает фиксированный заголовок и длину сообщения, Msg Len: 85, за которыми следует длина имени протокола и имя протокола.

Во второй области отображаются флаги CONNECT, которые соответствуют параметрам, которые мы установили при отправке сообщения.

Третья область показывает содержимое полезной нагрузки.Перед каждым содержимым есть два байта, указывающие длину содержимого.


Суммировать

Сегодня в MQTT представлены типы протоколов CONNECT и CONNACK. Тип протокола CONNECT содержит заголовки протокола, заголовки переменных и тела сообщений. Основное внимание уделяется флагам CONNECT и некоторым важным функциям в сообщении о соединении, в том числе Clean Session, Will Topic, Keep Alive, User/Password и т. д., которые применимы.

Кроме того, мы также представили CONNACK и, наконец, провели тест захвата пакетов в рамках эксперимента, чтобы проверить то, что мы сказали.

если у тебя есть


Все статьи вGithubСинхронизируйтесь, вы также можете посетить мойличный блогНажмите, чтобы просмотреть