Программирование ARM Стандарт MQTT 5 Fri, April 26 2024  

Поделиться

Нашли опечатку?

Пожалуйста, сообщите об этом - просто выделите ошибочное слово или фразу и нажмите Shift Enter.

Стандарт MQTT 5 Печать
Добавил(а) microsin   

[1. Терминология стандарта MQTT]

Сетевое соединение (Network Connection): передача данных нижележащим транспортным протоколом, который использует MQTT. Его функция:

• Подключает Клиента к Серверу.
• Предоставляет способ отправки последовательного, без потерь, потока данных в обоих направлениях.

Сообщение приложения (Application Message): данные, передаваемые по протоколу MQTT по сети для приложения. Когда сообщение передается по протоколу MQTT, в нем содержаться данные полезной нагрузки (payload), качества обслуживания (Quality of Service, QoS), набор свойств (Properties), и имя темы (Topic Name).

Клиент: программа или "умное" устройство, использующее MQTT. Клиент:

• Открывает сетевое соединение с Сервером.
• Публикует Application Messages, которыми могут интересоваться другие Клиенты.
• Подписывается на запрос Application Messages, которыми Клиент интересуется на приеме.
• Отписывается для удаления запроса на Application Messages.
• Закрывает сетевое соединение с Сервером.

Сервер: программа или устройство, которое действует как посредник между Клиентами, которые публикуют сообщения (Application Messages), такие Клиенты еще называют публишерами, и Клиентами, которые подписываются на получение таких сообщений (субскрайберы). Сервер:

• Принимает сетевые соединения от Клиентов.
• Принимает сообщения от Клиентов (публикаторов).
• Обрабатывает запросы от Клиентов (подписчиков) на подписку (Subscribe) или отписку (Unsubscribe) запросов сообщений.
• Перенаправляет Application Messages, которые совпадают с подписками Клиентов (Client Subscriptions).
• Закрывает сетевое соединение от Клиента.

Сессия: взаимодействие между Клиентом и Сервером с отслеживанием состояний. Некоторые сессии длятся только в пределах времени активности одного сетевого соединения, другие могут охватывать несколько последовательных сетевых соединений между Клиентом и Сервером.

Подписка (Subscription): подписка (частная) содержит фильтр тематики (Topic Filter) и максимальное качество обслуживания (QoS). Подписка связана с одной сессией. Сессия может содержать больше одной подписки. Каждая подписа в пределах сессии имеет отдельный Topic Filter.

Общая подписка (Shared Subscription): также содержит фильтр тематики и максимальное QoS. Shared Subscription может быть связана с больше чем одной сессией, чтобы обеспечить более широкий диапазон шаблонов обмена сообщениями. Application Message, которое соответствует Shared Subscription, отправляется только тому Клиенту, который ассоциирован с одной из этих сессий. Сессия можетбыть подписана на больше чем одну общую подписку, и может содержать как общие, так и частные подписки.

Wildcard Subscription: это подписка, где имеется Topic Filter с одним или несколькими символами массовой подстановки (wildcard). Это позволяет подписке соответствовать больше чем одному имени темы подписки (Topic Name). Подробнее см. секцию 4.7 для описания символов wildcard в Topic Filter.

Topic Name: метка, прикрепленная к Application Message, которая совпадает с подписками, известными Серверу.

Topic Filter: выражение, содержащееся в подписке, которое обозначает одну или несколько тем подписки. Topic Filter может включать символы wildcard.

MQTT Control Packet: пакет управления, информационный пакет, отправляемый через сетевое соединение. Спецификация MQTT определяет 15 различных типов MQTT Control Packet, например пакет PUBLISH используется для передачи Application Messages.

Malformed Packet: пакет управления, который не может быть обработан по спецификацией MQTT. См. секцию 4.13 для информации по обработке ошибок.

Protocol Error: ошибка, которая была обнаружена после парсинга пакета. Пакет содержит данные, которые не дозволяет протокол, или эти данные несовместимы с состоянием Клиента или Сервера (см. секцию 4.13).

Will Message: Application Message, которое публикуется Сервером после закрытия сетевого соединения, когда оно не было закрыто надлежащим образом. Описание таких сообщений см. в секции 3.1.2.5.

Disallowed Unicode code point: набор кодов управления Unicode, которые не должны включаться в строку, закодированную в UTF-8, подробнее см. секцию "UTF-8 Encoded String" врезки "Представление данных".

1.5.2. 2-байтное целое. Данные из 2 байт, хранящие uint16_t, расположенные в порядке big-endian: старший байт в памяти (ячейках буфера) предшествует младшему [3]. Это означает, что 16-разрядное слово представлено в сети так, что сначала идет старший байт (Most Significant Byte, MSB), за которым следует младший (Least Significant Byte, LSB).

1.5.3. 4-байтное целое. Хранит uint32_t в порядке байт big-endian.

1.5.4. UTF-8 Encoded String. Текстовые поля, показанные далее в описании MQTT Control Packet, закодированы строками в формате UTF-8. UTF-8 [RFC3629] это эффективный способ кодирования символов Unicode, совмещающий однобайтовое кодирование символов ASCII.

Каждая из таких строк имеет префикс из двухбайтового поля, которое даёт количество байт в самой строке, закодированной в UTF-8, как показано на рис. 1.1 ниже. Как следствие максимальный размер UTF-8 Encoded String составляет 65535 байт.

Если не указано нечто другое, то все строки, закодированные UTF-8, могут иметь длину от 0 до 65535 байт.

Бит 7 6 5 4 3 2 1 0
Байт 1 MSB длины строки
Байт 2 LSB длины строки
Байт 3 ... Данные символов UTF-8, если длина > 0.

Рис. 1.1. Структура UTF-8 Encoded String.

Символьные данные в UTF-8 Encoded String ДОЛЖНЫ содержать правильный формат UTF-8, как это определено спецификацией Unicode, и было дополнено в RFC 3629 [RFC3629]. В частности, данные символов НЕ ДОЛЖНЫ включать code points между U+D800 и U+DFFF[MQTT-1.5.4-1]. Если Клиент и Сервер приняли MQTT Control Packet содержащий неправильно сформированный UTF-8, то такой пакет обозначается как Malformed Packet. См. секцию 4.13 для информации по обработки ошибок.

Примечание: текст, выделенный желтым цветом в данной спецификации [1], определяет операторы соответствия. Каждому оператору соответствия присвоена ссылка в формате [MQTT-x.x.x-y], где x.x.x - номер раздела, а y - счетчик операторов в разделе.

UTF-8 Encoded String НЕ ДОЛЖНА включать кодирование null-символа U+0000[MQTT-1.5.4-2]. Если получатель (Сервер или Клиент) примет MQTT Control Packet, содержащий U+0000, то это Malformed Packet.

Данные НЕ ДОЛЖНЫ включать кодирования Unicode, перечисленные ниже. Если получатель (Сервер или Клиент) примет MQTT Control Packet, содержащий любой из таких символов, то такой пакет МОЖЕТ считаться как Malformed Packet. Эти коды называются Disallowed Unicode code points. См. секцию 5.4.9 для дополнительной информации по обработке Disallowed Unicode code points.

· U+0001..U+001F символы управления.
· U+007F..U+009F символы управления.
· Code points, определенные спецификацией Unicode как non-characters (например U+0FFFF).

Последовательность UTF-8 из байт 0xEF 0xBB 0xBF всегда интерпретируется как U+FEFF ("ZERO WIDTH NO-BREAK SPACE") всякий раз, когда она появляется строке, и она НЕ ДОЛЖНА быть пропущена или вырезана приемником пакетов[MQTT-1.5.4-3].

Пример неправильного форматирования. В качестве примера показана строка, которая содержит латинскую заглавную букву A, за которой идет code point U+2A6D4 (представляющий символ CJK IDEOGRAPH EXTENSION B), закодированная следующим образом:

Бит 7 6 5 4 3 2 1 0
Байт 1 MSB длины строки (0x00)
  0 0 0 0 0 0 0 0
Байт 2 LSB длины строки (0x05)
  0 0 0 0 0 1 0 1
Байт 3 'A' (0x41)
  0 1 0 0 0 0 0 1
Байт 4 (0xF0)
  1 1 1 1 0 0 0 0
Байт 5 (0xAA)
  1 0 1 0 1 0 1 0
Байт 6 (0x9B)
  1 0 0 1 1 0 1 1
Байт 7 (0x94)
  1 0 0 1 0 1 0 0

Рис. 1-2. Ненормативный пример UTF-8 Encoded String.

1.5.5. Variable Byte Integer. Это целое число с переменным количеством байт, закодированное по схеме, когда значение до 127 закодировано только одним байтом. Значения больше 127 кодируются следующим образом. Младшие 7 бит каждого байта кодируют данные, а самый старший бит используется для индикации, имеются ли следующие байты для представления числа. Таким образом, каждый байт кодирует 128 значений, и "бит продолжения". Для поля типа Variable Byte Integer может использоваться максимум 4 байта. Закодированное значение ДОЛЖНО использовать минимально необходимое количество байт, необходимое для кодирования числа[MQTT-1.5.5-1]. Это показано ниже в таблице 1-1.

Таблица 1-1. Размер Variable Byte Integer.

Цифры От До
1 0 (0x00) 127 (0x7F)
2 128 (0x80, 0x01) 16383 (0xFF, 0x7F)
3 16384 (0x80, 0x80, 0x01) 2097151 (0xFF, 0xFF, 0x7F)
4 2097152 (0x80, 0x80, 0x80, 0x01) 268435455 (0xFF, 0xFF, 0xFF, 0x7F)

Для кодирования неотрицательного целого числа (X) в Variable Byte Integer используется следующий алгоритм:

do
   encodedByte = X MOD 128
   X = X DIV 128
   // если здесь больше данных для кодирования, то установить старший бит этого байта
   if (X > 0)
      encodedByte = encodedByte OR 128
   endif
   'output' encodedByte
while (X > 0)

В этом алгоритме MOD представляет оператор modulo (% на языке C), DIV целочисленное деление (/ на C), и OR это логическая операция ИЛИ (| на C).

Алгоритм декодирования типа Variable Byte Integer:

multiplier = 1
value = 0
do
   encodedByte = 'следующий байт из потока'
   value += (encodedByte AND 127) * multiplier
   if (multiplier > 128*128*128)
      throw Error(Malformed Variable Byte Integer)
   multiplier *= 128
while ((encodedByte AND 128) != 0)

Здесь AND это логическая операция И (& in C).

Когда алгоритм завершится, value содержит значение Variable Byte Integer.

1.5.6. Binary Data. Двоичные данные представлены 2-байтным целым, обозначающее количество байт, которое идет дальше. Таким образом, длина Binary Data ограничена диапазоном от до 65535 байт.

1.5.7. UTF-8 String Pair. Состоит из двух UTF-8 Encoded String. Этот тип данных используется для хранения значений имя-значение. Первая строка это имя, и вторая строка это значение.

Обе строки в паре должны удовлетворять требованиям кодирования UTF-8[MQTT-1.5.7-1]. Если получатель (Клиент или Сервер) примет пару строк, которая не удовлетворяет этим требованиям, то такой случай считается ошибочно сформированным пакетом (Mailformed Packet). По поводу обработки этой ошибки и других ошибок см. секцию 4.13.

Security. Реализации MQTT Клиент и Сервер ДОЛЖНЫ предлагать опции аутентификации (Authentication), авторизации (Authorization) и защищенной коммуникации, как обсуждается в Главе 5. Для приложений, имеющим дело с данными критической инфраструктуры, такой как персональные данные или другая нежелательная к утечке информация, настоятельно рекомендуется использовать эти возможности по безопасности.

Это взаимозависимые понятия, и со схожими названиями, поэтому их назначение часто путают.

Аутентификация – процедура проверки подлинности, например, проверка подлинности пользователя путем сравнения введенного им пароля с паролем, сохраненным в базе данных. Авторизация – предоставление определенному лицу прав на выполнение определенных действий.

MQTT v5.0. MQTT v5.0 добавляет значительное количество новых функций MQTT, сохраняя основную часть ядра. Основные функциональные улучшения:

· Улучшения для масштабируемости в больших системах.
· Улучшено сообщение об ошибках.
· Формализованы основные шаблоны, включая обнаружение возможностей и ответ на запрос.
· Механизмы расширения, включающие параметры пользователя.
· Улучшения производительности и поддержка малых Клиентов.

См. приложение Appendix C [1] для описания общих изменений в MQTT v5.0.

[2. Формат MQTT Control Packet]

2.1. Структура MQTT Control Packet. Протокол MQTT работает через обмен MQTT Control Packet следующими друг за другом в определенной последовательности. В этой секции описан формат этих пакетов.

MQTT Control Packet содержит до из нескольких частей, от 1 до 3, которые всегда идут друг за другом в следующем порядке:

Fixed Header, представлен во всех MQTT Control Packet
Variable Header, представлен в некоторых MQTT Control Packet
Payload, представлена в некоторых MQTT Control Packet

Рис. 2.1. Структура MQTT Control Packet.

2.1.1. Fixed Header. Каждый MQTT Control Packet содержит следующий фиксированный заголовок:

Бит     7         6         5         4     3 2 1 0
Байт 1 Тип MQTT Control Packet Флаги, специфичные для каждого типа
Байт 2 ... Remaining Length

Рис. 2-2. Формат Fixed Header.

2.1.2. Тип MQTT Control Packet. Позиция: byte 1, биты 7-4. Представлен 4-битным значением без знака:

Таблица 2-1. Типы MQTT Control Packet.

Имя Знач. Направление потока Описание
Зарезервировано 0 Запрещено Зарезервировано
CONNECT 1 Клиент → Сервер Запрос на соединение
CONNACK 2 Сервер → Клиент Подтверждение соединения
PUBLISH 3 Клиент → Сервер или
Сервер → Клиент
Публикация сообщения
PUBACK 4 Клиент → Сервер или
Сервер → Клиент
Подтверждение публикации (QoS1)
PUBREC 5 Клиент → Сервер или
Сервер → Клиент
Публикация принятого (доставка QoS2 часть 1)
PUBREL 6 Клиент → Сервер или
Сервер → Клиент
Релиз публикации (доставка QoS2 часть 2)
PUBCOMP 7 Клиент → Сервер или
Сервер → Клиент
Завершение публикации (доставка QoS2 часть 3)
SUBSCRIBE 8 Клиент → Сервер Запрос на подписку
SUBACK 9 Сервер → Клиент Подтверждение подписки
UNSUBSCRIBE 10 Клиент → Сервер Запрос на отписку
UNSUBACK 11 Сервер → Клиент Подтверждение отписки
PINGREQ 12 Клиент → Сервер Запрос PING
PINGRESP 13 Сервер → Клиент Ответ на PING
DISCONNECT 14 Клиент → Сервер или
Сервер → Клиент
Оповещение об отключении
AUTH 15 Клиент → Сервер или
Сервер → Клиент
Обмен в процессе аутентификации

2.1.3. Флаги. Остальные биты [3-0] byte 1 в Fixed Header содержат флаги, специфичные для каждого типа MQTT Control Packet, как показано ниже. Где бит флага помечен как "Reserved", он зарезервирован для использования в будущем, и ДОЛЖЕН быть установлен в перечисленное значение[MQTT-2.1.3-1]. Если приняты недопустимые флаги, то это Malformed Packet (см. секцию 4.13).

Таблица 2-2. Биты флагов.

MQTT Control Packet Флаги Fixed Header Бит 3 Бит 2 Бит 1 Бит 0
CONNECT Зарезервировано 0 0 0 0
CONNACK Зарезервировано 0 0 0 0
PUBLISH Используется в MQTT v5.0 DUP QoS RETAIN
PUBACK Зарезервировано 0 0 0 0
PUBREC Зарезервировано 0 0 0 0
PUBREL Зарезервировано 0 0 1 0
PUBCOMP Зарезервировано 0 0 0 0
SUBSCRIBE Зарезервировано 0 0 1 0
SUBACK Зарезервировано 0 0 0 0
UNSUBSCRIBE Зарезервировано 0 0 1 0
UNSUBACK Зарезервировано 0 0 0 0
PINGREQ Зарезервировано 0 0 0 0
PINGRESP Зарезервировано 0 0 0 0
DISCONNECT Зарезервировано 0 0 0 0
AUTH Зарезервировано 0 0 0 0

DUP = дублированная доставка пакета PUBLISH.
QoS = PUBLISH Quality of Service.
RETAIN = флаг сохраненного сообщения PUBLISH.

См. секцию 3.3.1 для описание флагов DUP, QoS и RETAIN в пакете PUBLISH.

2.1.4. Remaining Length (оставшаяся длина). Позиция: начинается на byte 2.

Оставшаяся длина байт Variable Byte Integer в текущем Control Packet, включая данные Variable Header и Payload. Remaining Length не включает байты, используемые для кодирования Remaining Length. Размер пакета это общее количество байт в MQTT Control Packet, который равен длине Fixed Header плюс Remaining Length.

2.2. Variable Header. Некоторые типы MQTT Control Packet содержат компонент заголовка переменной длины (Variable Header). Он находится между Fixed Header и Payload. Содержимое Variable Header меняется в зависимости от типа пакета. Поле идентификатора пакета (Packet Identifier) в Variable Header общее в некоторых типах пакетов.

2.2.1. Packet Identifier. Компонент Variable Header многих типов MQTT Control Packet включает в себя 2-байтное целочисленное поле идентификатора пакета (Packet Identifier). К этим MQTT Control Packet относятся PUBLISH (где QoS > 0), PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK.

Типы MQTT Control Packet, которые требуют Packet Identifier, показаны в следующей таблице:

Таблица 2-3. Пакеты MQTT Control, содержащие Packet Identifier.

MQTT Control Packet Поле Packet Identifier
CONNECT Нет
CONNACK Нет
PUBLISH Есть (если QoS > 0)
PUBACK Есть
PUBREC Есть
PUBREL Есть
PUBCOMP Есть
SUBSCRIBE Есть
SUBACK Есть
UNSUBSCRIBE Есть
UNSUBACK Есть
PINGREQ Нет
PINGRESP Нет
DISCONNECT Нет
AUTH Нет

Пакет PUBLISH НЕ ДОЛЖЕН содержать Packet Identifier, если значение QoS установлено в 0[MQTT-2.2.1-2].

Каждый раз, когда Клиент посылает новый SUBSCRIBE, UNSUBSCRIBE или PUBLISH (где QoS > 0) MQTT Control Packet, он ДОЛЖЕН назначить ему ненулевой Packet Identifier, который в настоящее время не используется[MQTT-2.2.1-3].

Каждый раз, когда Сервер посылает новый PUBLISH (где QoS > 0) MQTT Control Packet, он ДОЛЖЕН назначить ему ненулевой Packet Identifier, который в настоящее время не используется[MQTT-2.2.1-4].

Packet Identifier становится доступным для использования после того, как отправитель обработал соответствующий пакет подтверждения, определенный следующим образом. В случае QoS 1 PUBLISH это соответствующий PUBACK; в случае QoS 2 PUBLISH это PUBCOMP или PUBREC с Reason Code 128 или больше. Для SUBSCRIBE или UNSUBSCRIBE это соответствующий SUBACK или UNSUBACK.

Идентификаторы пакета используются вместе с PUBLISH, SUBSCRIBE и UNSUBSCRIBE от одного, унифицированного набора идентификаторов, отдельно в сессии для Клиента и Сервера. Packet Identifier не может использоваться одновременно в более чем одной команде.

Пакет PUBACK, PUBREC, PUBREL или PUBCOMP ДОЛЖЕН содержать такой же Packet Identifier, как и пакет PUBLISH, который был изначально отправлен[MQTT-2.2.1-5]. SUBACK и UNSUBACK ДОЛЖЕН содержать Packet Identifier, который был использован в соответствующем пакете SUBSCRIBE и UNSUBSCRIBE[MQTT-2.2.1-6].

Клиент и Сервер присваивают идентификаторы независимо друг от друга. В результате пары Клиент-Сервер могут принимать участие в одновременных сеансах обмена сообщениями, используя одинаковые Packet Identifier.

Замечание: есть возможность для Клиента отправить PUBLISH-пакет с Packet Identifier 0x1234 и затем принять другой PUBLISH-пакет с Packet Identifier 0x1234 от Сервера до того, как он получит PUBACK от отправленного им пакета PUBLISH.

Клиент                                  Сервер 
PUBLISH Packet Identifier=0x1234 →
                                        ← PUBLISH Packet Identifier=0x1234
PUBACK Packet Identifier=0x1234  →
                                        ← PUBACK Packet Identifier=0x1234

2.2.2. Properties. Последнее поле в Variable Header пакета CONNECT, CONNACK, PUBLISH, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, DISCONNECT и AUTH устанавливает свойства (Properties). В пакете CONNECT есть также опциональный набор свойств в поле Will Properties с Payload.

Набор свойств состоит из длины свойства (Property Length), за которой идут свойства (Properties).

2.2.2.1. Property Length. Длина свойства закодирована как Variable Byte Integer. Длина свойства не включает байты, используемые для кодирования самой длины свойства, но включает длину свойств (Properties). Если нет свойств, то это ДОЛЖНО быть показано подключением нулевого Property Length[MQTT-2.2.2-1].

2.2.2.2. Property. Свойство (Property) состоит из идентификатора, который определяет его использование и тип данных, за которым следует значение. Идентификатор закодирован как Variable Byte Integer. Control Packet, который содержит идентификатор, недопустимый для этого типа пакета, или содержит значение, у которого тип не тот, считается как Malformed Packet. Если такой пакет принят, используйте пакет CONNACK или DISCONNECT с Reason Code 0x81 (Malformed Packet), как это описано в секции 4.13 с описанием обработки ошибок. Не имеет значения порядок следования свойств с различными идентификаторами.

Таблица 2-4. Properties (свойства).

ID
Имя (использование)
Тип Packet / Will Properties
Dec Hex
1 0x01 Payload Format Indicator Byte PUBLISH, Will Properties
2 0x02 Message Expiry Interval Four Byte Integer PUBLISH, Will Properties
3 0x03 Content Type UTF-8 Encoded String PUBLISH, Will Properties
8 0x08 Response Topic UTF-8 Encoded String PUBLISH, Will Properties
9 0x09 Correlation Data Binary Data PUBLISH, Will Properties
11 0x0B Subscription Identifier Variable Byte Integer PUBLISH, SUBSCRIBE
17 0x11 Session Expiry Interval Four Byte Integer CONNECT, CONNACK, DISCONNECT
18 0x12 Assigned Client Identifier UTF-8 Encoded String CONNACK
19 0x13 Server Keep Alive Two Byte Integer CONNACK
21 0x15 Authentication Method UTF-8 Encoded String CONNECT, CONNACK, AUTH
22 0x16 Authentication Data Binary Data CONNECT, CONNACK, AUTH
23 0x17 Request Problem Information Byte CONNECT
24 0x18 Will Delay Interval Four Byte Integer Will Properties
25 0x19 Request Response Information Byte CONNECT
26 0x1A Response Information UTF-8 Encoded String CONNECT
28 0x1C Server Reference UTF-8 Encoded String CONNACK, DISCONNECT
31 0x1F Reason String UTF-8 Encoded String CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT, AUTH
33 0x21 Receive Maximum Two Byte Integer CONNECT, CONNACK
34 0x22 Topic Alias Maximum Two Byte Integer CONNECT, CONNACK
35 0x23 Topic Alias Two Byte Integer PUBLISH
36 0x24 Maximum QoS Byte CONNACK
37 0x25 Retain Available Byte CONNACK
38 0x26 User Property UTF-8 Encoded String CONNECT, CONNACK, PUBLISH, Will Properties, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK, DISCONNECT, AUTH
39 0x27 Maximum Packet Size Four Byte Integer CONNECT, CONNACK
40 0x28 Wildcard Subscription Available Byte CONNACK
41 0x29 Subscription Identifier Available Byte CONNACK
42 0x2A Shared Subscription Available Byte CONNACK

Замечание: хотя Property Identifier определен ака Variable Byte Integer, в этой версии стандарта все идентификаторы свойства имеют длину в один байт (диапазона кодов 0 .. 127 вполне достаточно).

2.3. Payload (данные полезной нагрузки). Некоторые MQTT Control Packet содержат Payload как последнюю часть пакета. В пакете PUBLISH это Application Message.

Таблица 2-5. Пакеты управления (MQTT Control Packet), которые содержат Payload.

MQTT Control Packet Полезная нагрузка
CONNECT Требуется
CONNACK Нет
PUBLISH Опционально
PUBACK Нет
PUBREC Нет
PUBREL Нет
PUBCOMP Нет
SUBSCRIBE Требуется
SUBACK Требуется
UNSUBSCRIBE Требуется
UNSUBACK Требуется
PINGREQ Нет
PINGRESP Нет
DISCONNECT Нет
AUTH Нет

2.4. Reason Code. Это однобайтное значение без знака, которое показывает результат операции. Reason-коды значениями меньше 0x80 обозначают успешное завершение операции. Нормальный Reason Code для успеха равен 0. Значения Reason Code 0x80 или больше показывают ошибку (failure).

У пакетов управления CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, DISCONNECT и AUTH имеется один Reason Code как часть Variable Header. Пакеты SUBACK и UNSUBACK содержат в Payload список одного или нескольких Reason Code.

Значения Reason Code используют один и тот же набор значений, показанный в таблице ниже.

Таблица 2-6. Значения Reason Code.

Reason Code
Имя
Пакеты
Dec Hex
0 0x00 Успешное завершение CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, UNSUBACK, AUTH
0 0x00 Нормальное отключение DISCONNECT
0 0x00 Предоставлено QoS0 SUBACK
1 0x01 Предоставлено QoS1 SUBACK
2 0x02 Предоставлено QoS2 SUBACK
4 0x04 Отключение с Will Message DISCONNECT
16 0x10 Нет подходящих подписчиков PUBACK, PUBREC
17 0x11 Подписка не существует UNSUBACK
24 0x18 Продолжение аутентификации AUTH
25 0x19 Повторная аутентификация AUTH
128 0x80 Неопределенная ошибка CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
129 0x81 Malformed Packet CONNACK, DISCONNECT
130 0x82 Protocol Error CONNACK, DISCONNECT
131 0x83 Ошибка, специфичная для реализации CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
132 0x84 Не поддерживаемая версия протокола CONNACK
133 0x85 Недопустимый идентификатор клиента CONNACK
134 0x86 Ошибка User Name или Password CONNACK
135 0x87 Не авторизовано CONNACK, PUBACK, PUBREC, SUBACK, UNSUBACK, DISCONNECT
136 0x88 Сервер недоступен CONNACK
137 0x89 Сервер занят CONNACK, DISCONNECT
138 0x8A Banned CONNACK
139 0x8B Завершение работы сервера DISCONNECT
140 0x8C Неправильный метод аутентификации CONNACK, DISCONNECT
141 0x8D Таймаут Keep Alive DISCONNECT
142 0x8E Session taken over DISCONNECT
143 0x8F Недопустимый Topic Filter SUBACK, UNSUBACK, DISCONNECT
144 0x90 Недопустимое Topic Name CONNACK, PUBACK, PUBREC, DISCONNECT
145 0x91 Packet Identifier уже используется PUBACK, PUBREC, SUBACK, UNSUBACK
146 0x92 Packet Identifier не найден PUBREL, PUBCOMP
147 0x93 Превышен Receive Maximum DISCONNECT
148 0x94 Недопустимый Topic Alias DISCONNECT
149 0x95 Пакет слишком большой CONNACK, DISCONNECT
150 0x96 Частота выдачи сообщений слишком большая DISCONNECT
151 0x97 Превышена квота CONNACK, PUBACK, PUBREC, SUBACK, DISCONNECT
152 0x98 Административное действие DISCONNECT
153 0x99 Недопустимый формат полезной нагрузки CONNACK, PUBACK, PUBREC, DISCONNECT
154 0x9A Retain не поддерживается CONNACK, DISCONNECT
155 0x9B QoS не поддерживается CONNACK, DISCONNECT
156 0x9C Используйте другой сервер CONNACK, DISCONNECT
157 0x9D Сервер перемещен CONNACK, DISCONNECT
158 0x9E Общие подписки не поддерживаются SUBACK, DISCONNECT
159 0x9F Превышена частота подключений CONNACK, DISCONNECT
160 0xA0 Максимальное время подключения DISCONNECT
161 0xA1 Идентификаторы подписки не поддерживаются SUBACK, DISCONNECT
162 0xA2 Wildcard подписки не поддерживаются SUBACK, DISCONNECT

Замечание: при Reason Code 0x91 (идентификатор пакета уже используется) ответом на это может либо попытка исправить состояние, или сбросить состояние сессии (Session state) путем соединения, используя Clean Start, установленный в 1, или разобраться, какая из реализаций Клиента или Сервера содержит ошибку.

[3. MQTT Control Packets]

3.1. CONNECT – Connection Request (запрос на соединение). После того, как между Клиентом и Сервером установлено сетевое соединение, первый отправленный Клиентом на Сервер пакет ДОЛЖЕН БЫТЬ пакетом CONNECT[MQTT-3.1.0-1].

Клиент может отправить пакет CONNECT на сетевом соединении только 1 раз. Сервер ДОЛЖЕН обработать второй пакет, отправленный Клиентом, как ошибку протокола (Protocol Error), и закрыть сетевое соединение[MQTT-3.1.0-2]. См. секцию 4.13 для информации по обработке ошибок.

Payload содержит одно или большее количество закодированных полей. Они указывают уникальный идентификатор Клиента, Will Topic, Will Payload, User Name и Password. Все, кроме идентификатора Клиента, может быть опущено, и присутствие полей определяется по флагам в Variable Header.

3.1.1. CONNECT Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (1) Зарезервировано
  0 0 0 1 0 0 0 0
Байт 2... Remaining Length

Рис. 3-1. Fixed Header пакета CONNECT.

Поле Remaining Length. Это длина Variable Header плюс длина Payload. Оно закодировано как Variable Byte Integer.

3.1.2. CONNECT Variable Header. Заголовок перемененной длины (Variable Header) для пакета CONNECT содержит следующие поля в указанном порядке: Protocol Name, Protocol Level, Connect Flags, Keep Alive и Properties. Правила для кодирования Properties описаны выше в секции 2.2.2.

3.1.2.1. Protocol Name.

  Описание 7 6 5 4 3 2 1 0
Имя протокола
Байт 1 MSB длины (0) 0 0 0 0 0 0 0 0
Байт 2 LSB длины (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

Рис. 3-2. Байты Protocol Name.

Protocol Name это строка UTF-8, представляющая имя протокола "MQTT" большими буквами. Эта строка, её смещение и длина не будет меняться в будущих версиях спецификации MQTT.

Сервер, который поддерживает несколько протоколов, использует Protocol Name для определения, что данные относятся к MQTT. Имя протокола ДОЛЖНО быть строкой UTF-8 "MQTT". Если Сервер не хочет принять CONNECT и хочет показать, что он является Сервером MQTT, то он МОЖЕТ послать ракет CONNACK с Reason Code 0x84 (Unsupported Protocol Version), и затем ДОЛЖЕН закрыть сетевое соединение[MQTT-3.1.2-1].

Замечание: замечание анализаторы пакетов, такие как файерволл, могут использовать Protocol Name для идентификации трафика MQTT.

3.1.2.2. Protocol Version.

  Описание 7 6 5 4 3 2 1 0
Уровень протокола
Байт 7 Версия (5) 0 0 0 0 0 1 0 1

Рис. 3‑3. Байт Protocol Version.

Однобайтовое значение без знака, обозначающее уровень ревизии протокола, используемое Клиентом. Значение Protocol Version для версии протокола 5.0 равно 5 (0x05).

Сервер, который поддерживает несколько версий протокола MQTT, использует Protocol Version для определения, какую версию MQTT использует Клиент. Если Protocol Version не 5, и Сервер не хочет принять пакет CONNECT, то Сервер МОЖЕТ послать ракет CONNACK с Reason Code 0x84 (Unsupported Protocol Version), и затем ДОЛЖЕН закрыть сетевое соединение[MQTT-3.1.2-2].

3.1.2.3. Connect Flags. Байт флагов соединения (Connect Flags) содержит несколько параметров, указывающих поведение соединения MQTT. Он также показывает присутствие или отсутствие полей в Payload.

Бит     7         6         5     4 3 2 1 0
  Флаг User Name Флаг Password Will Retain Will QoS Флаг Will Clean Start Зарезервировано
Байт 8 X X X X X X X X

Рис. 3‑4. Биты Connect Flags.

Сервер ДОЛЖЕН проверить, что зарезервированный флаг в пакете CONNECT установлен в 0[MQTT-3.1.2-3]. Если это не так, то это Malformed Packet. См. секцию 4.13 для получение информации по обработке ошибок.

3.1.2.4. Clean Start. Этот бит флагов показывает, запущена ли соединением в новая сессия, или это продолжение существующей сессии. См. секцию 4.1 для определения состояния сессии (Session State).

Если принят пакет CONNECT, в котором Clean Start установлен в 1, то Клиент и Сервер ДОЛЖНЫ отбросить любую существующую сессию и начать новую сессию[MQTT-3.1.2-4]. Как следствие, флаг присутствия сессии (флаг Present) в CONNACK всегда устанавливается в 0, если Clean Start установлен в 1.

Если принят пакет CONNECT, в котором Clean Start установлен в 0, и имеется сессия, связанная с Client Identifier, то Сервер ДОЛЖЕН возобновить коммуникации с Клиентом, основываясь на состоянии из существующей сессии[MQTT-3.1.2-5]. Если принят пакет CONNECT, в котором Clean Start установлен в 0, и нет сессии, связанной с Client Identifier, то Сервер ДОЛЖЕН создать новую сессию[MQTT-3.1.2-6].

3.1.2.5. Will Flag. Если Will Flag установлен в 1, то это показывает, что Will Message ДОЛЖНО быть сохранено на Сервере и ассоциировано с сессией[MQTT-3.1.2-7]. Will Message содержит поля свойства (Will Properties), темы (Will Topic) и полезной нагрузки (Will Payload) в CONNECT Payload. Will Message ДОЛЖНО быть опубликовано после последующего закрытия сетевого соединения: либо после истечения Will Delay Interval или окончании сессии, если Will Message не было удалено Сервером на приеме пакета DISCONNECT с Reason Code 0x00 (Normal disconnection), либо когда сетевое соединение для ClientID открыто перед истечением Will Delay Interval[MQTT-3.1.2-8].

Ситуации, в которых Will Message публикуется, включает, но не ограничивается следующим:

• Сервером обнаружена ошибка ввода/вывода (I/O error) или проблема сети (network failure).
• Клиент не смог поддержать коммуникацию в пределах времени Keep Alive.
• Клиент закрыл сетевое соединение без отправки пакета DISCONNECT с Reason Code 0x00 (нормальное разъединение).
• Сервер закрыл сетевое соединения без предварительного приема пакета DISCONNECT с Reason Code 0x00 (нормальное разъединение).

Если Will Flag установлен в 1, то в полезной нагрузке Payload ДОЛЖНЫ присутствовать поля Will Properties, Will Topic и Will Payload[MQTT-3.1.2-9]. Will Message ДОЛЖНО быть удалено из сохраненного на Сервере состояния сессии (Session State), как только оно было опубликовано, или Сервер принял от Клиента пакет DISCONNECT с Reason Code 0x00 (нормальное разъединение)[MQTT-3.1.2-10].

Сервер ДОЛЖЕН опубликовать сообщения Will Message сразу же после закрытия сетевого соединения и после истечения Will Delay Interval, или при завершении сессии, в зависимости от того, что произойдет первым. В случае выключения Сервера (Server shutdown) или отказа Сервера (Server failure) Сервер МОЖЕТ отложить публикацию сообщений Will Message до своего последующего рестарта. Если это произошло, то может пройти некоторое время между моментом, когда Сервер столкнулся с неожиданной ошибкой, и моментом публикации Will Message.

Для информации по Will Delay Interval обратитесь к секции 3.1.3.2.

Замечание: Клиент может договориться о том, что Will Message оповестит об истечении сессии (Session Expiry) путем установки Will Delay Interval дольше, чем Session Expiry Interval, и отправки DISCONNECT с Reason Code 0x04 (разъединение с Will Message).

3.1.2.6. Will QoS. Два бита в позиции 4 и 3 Connect Flags указывают уровень качества обслуживания (QoS), используемый при публикации Will Message.

Если Will Flag установлен в 0, то Will QoS ДОЛЖНО быть установлено в 0 (0x00)[MQTT-3.1.2-11].

Если Will Flag установлен в 1, то значение Will QoS может быть 0 (0x00), 1 (0x01), или 2 (0x02)[MQTT-3.1.2-12]. Значение 3 (0x03) означает Malformed Packet. См. секцию 4.13 для информации по обработке ошибок.

3.1.2.7. Will Retain. Этот бит указывает, должно ли быть сохранено Will Message при публикации.

Если Will Flag установлен в 0, то Will Retain ДОЛЖЕН быть установлен в 0[MQTT-3.1.2-13]. Если Will Flag установлен в 1, и Will Retain установлен в 0, то Сервер ДОЛЖЕН опубликовать Will Message как не сохраняемое сообщение[MQTT-3.1.2-14]. Если Will Flag установлен в 1, и Will Retain установлен в 1, то Сервер ДОЛЖЕН опубликовать Will Message как сохраняемое сообщение[MQTT-3.1.2-15].

3.1.2.8. User Name Flag. Этот бит находится в позиции 7 Connect Flags.

Если User Name Flag установлен в 0, то User Name НЕ ДОЛЖНО присутствовать в Payload[MQTT-3.1.2-16]. Если User Name Flag установлен в 1, то User Name ДОЛЖНО присутствовать в Payload[MQTT-3.1.2-17].

3.1.2.9. Password Flag. Этот бит находится в позиции 6 Connect Flags.

Если Password Flag установлен в 0, то пароль (Password) НЕ ДОЛЖЕН присутствовать в Payload[MQTT-3.1.2-18]. Если Password Flag установлен в 1, то пароль ДОЛЖЕН присутствовать в Payload[MQTT-3.1.2-19].

Замечание: эта версия протокола позволяет послать Password без User Name, в то время как MQTT v3.1.1 это не дозволяет. Это отражает использование Password учетных данных, не относящихся к паролю.

3.1.2.10. Keep Alive.

Бит 7 6 5 4 3 2 1 0
Байт 9 MSB Keep Alive
Байт 10 LSB Keep Alive

Рис. 3‑5. Байты Keep Alive.

Keep Alive это двухбайтное целое, обозначающее интервал времени в секундах. Это максимальный интервал времени между пакетами Клиента (интервал между моментом, когда Клиент завершил отправку одного MQTT Control Packet и моментом, когда он начал отправку следующего MQTT Control Packet). В зоне ответственности Клиента гарантировать, что интервал между событиями MQTT Control Packet не превышает значение Keep Alive. Если Keep Alive не 0, и нет отправки любых других MQTT Control Packet, то для поддержания сессии Клиент ДОЛЖЕН отправить пакет PINGREQ[MQTT-3.1.2-20].

Если Сервер возвратил Server Keep Alive в пакете CONNACK, то Клиент ДОЛЖЕН использовать это значение интервала вместо значения, отправленного Клиентом Keep Alive[MQTT-3.1.2-21].

Клиент может отправить PINGREQ в любой момент времени, независимо от значения Keep Alive, и проверить соответствующий PINGRESP, чтобы определить доступность сети и Сервера.

Если значение Keep Alive ненулевое, и Сервер не принимает MQTT Control Packet от Клиента в течение 1.5 интервала времени Keep Alive, то Сервер ДОЛЖЕН закрыть сетевое соединение с Клиентом как следствие отказа сети[MQTT-3.1.2-22].

Если Клиент не принял пакет PINGRESP в течение разумного времени после того, как он отправил PINGREQ, то он ДОЛЖЕН закрыть сетевое соединение с Сервером.

Значение Keep Alive 0 дает эффект отключения механизма Keep Alive. Если Keep Alive 0, то Клиент не обязан посылать MQTT Control Packet по какому-то конкретному расписанию.

Замечания: у Сервера могут быть другие причины отключения от Клиента, например из-за выключения. Установка Keep Alive не гарантирует, что Клиент останется подключенным. Реальное значение Keep Alive относится к специфике приложения, обычно оно составляет несколько минут. Максимальное значение 65535 соответствует 18 часам, 12 минутам и 15 секундам.

3.1.2.11. CONNECT Properties.

3.1.2.11.1. Property Length. Длина свойств Properties в заголовке переменной длины (Variable Header) пакета CONNECT, закодированная как Variable Byte Integer.

3.1.2.11.2. Session Expiry Interval. 17 (0x11), идентификатор интервала времени истечения сессии (Session Expiry Interval). За ним идет 4-байтное целое, представляющее интервал истечения сессии в секундах. Если Session Expiry Interval подключен больше одного раза, то это Protocol Error.

Если Session Expiry Interval отсутствует, то используется значение 0. Если он установлен в 0, или отсутствует, то сессия завершается при закрытии сетевого соединения.

Если Session Expiry Interval 0xFFFFFFFF (UINT_MAX), то сессия длится бесконечно.

Клиент и Сервер ДОЛЖНЫ сохранять Session State после того. как сетевое соединение было закрыто, если Session Expirity Interval больше 0[MQTT-3.1.2-23].

Замечание: отсчет времени на Клиенте или Сервере может не работать в определенные интервалы времени, например из-за того, что Клиент или Сервер тогда не находились в работе. Это может привести к задержке удаления состояния.

Для дополнительной информации о сессиях обратитесь к секции 4.1. В частности, секция 4.1.1 описывает ограничения сохраненного состояния.

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

Замечания:

1. По стандарту MQTT Specification Version 3.1.1 установка Clean Start в 1 и Session Expiry Interval в 0 эквивалентно установке CleanSession в 1. В этом стандарте установка Clean Start в 0 и без Session Expiry Interval эквивалентно установке CleanSession в 0.

2. Клиент, которому нужно обрабатывать сообщения только во время соединения, установит Clean Start в 1, установит Session Expiry Interval в 0. Он не будет принимать Application Messages, опубликованные до момента его соединения, и должен при каждом подключении заново подписываться на любые темы, которые его интересуют.

3. Клиент может подключаться к Серверу с использованием сети, обеспечивающей прерывистое соединение. Этот Клиент может использовать короткий Session Expiry Interval, чтобы можно было заново подключиться, когда сеть снова станет доступной, и продолжить надежную доставку сообщения. Если Клиент не переподключается, позволяя истечь сессии, то Application Messages пропадут.

4. Когда Клиент подключается с долгим Session Expiry Interval, он тем самым запрашивает у Сервера поддерживать состояние сессии MQTT на расширенный период времени после своего отключения. Клиенты должны подключаться с длительным Session Expiry Interval только если они намерены переподключаться к Серверу несколько позже. Когда Клиент определил, что больше не будет использовать сессию, он должен отключиться с установленным в 0 Session Expiry Interval.

5. Клиент всегда должен использовать флаг Session Present в CONNACK, чтобы определить, есть ли у Сервера состояние сессии (Session State) для этого Клиента.

6. Клиент может избежать своей собственной реализации истечения сессии, вместо этого полагаясь на флаг Session Present, возвращенный Сервером, чтобы определить, истекла ли сессия. Если Клиент реализовал свое собственное отслеживание истечения сессии, то он должен сохранять время, в течение которого Session State будет удалено, как часть своего Session State.

3.1.2.11.3. Receive Maximum. 33 (0x21), идентификатор Receive Maximum. За ним идет двухбайтное целое, представляющее значение Receive Maximum. Если значение Receive Maximum появляется несколько раз, или передает значение 0, то это Protocol Error.

Клиент использует значение Receive Maximum, чтобы ограничить число публикаций QoS 1 и QoS 2, обрабатываемых одновременно. Не существует механизма ограничения публикаций QoS 0, которые Сервер может пытаться отправить.

Значение Receive Maximum применяется только к текущему сетевому соединению. Если значение Receive Maximum отсутствует, то его значение по умолчанию 65535.

Для подробностей, как использовать Receive Maximum, обратитесь к секции 4.9 Flow Control.

3.1.2.11.4. Maximum Packet Size. 39 (0x27), идентификатор Maximum Packet Size. За ним идет 4-байтное целое, представляющее максимально допустимый для Клиента размер пакета. Если Maximum Packet Size не представлен, то не накладывается предел на размер пакета за пределами ограничений в протоколе в результате кодирования оставшейся длины и размеров заголовков протокола.

Подключение Maximum Packet Size больше одного раза или установка его значения в 0 соответствует Protocol Error.

Замечание: приложение отвечает за выбор подходящего значения Maximum Packet Size, если оно выбрало ограничить максимальный размер пакета.

Размер пакета это общее количество байт в MQTT Control Packet, как это определено в секции 2.1.4. Клиент использует Maximum Packet Size для информирования Сервера, то он не будет обрабатывать пакеты, размер которых превышает этот лимит.

Сервер НЕ ДОЛЖЕН посылать Клиенту пакеты с размером, превышающим Maximum Packet Size[MQTT-3.1.2-24]. Если Клиент получил пакет, превышающий этот лимит, то это Protocol Error, и Клиент использует DISCONNECT с Reason Code 0x95 (Packet too large), как это описано в секции 4.13.

Когда пакет слишком велик для отправки, Сервер ДОЛЖЕН его отбросить зе отправки, и затем вести себя так, как если бы он отправил это Application Message[MQTT-3.1.2-25].

В случае, когда существует общая подписка (Shared Subscription), где есть слишком большое сообщение для отправки одному или нескольким Клиентам, но есть другие Клиенты, которые могут такое большое сообщение принять, то Сервер может выбрать либо отбросить сообщение без его отправки кому-либо из Клиентов, либо отправить сообщение тем Клиентам, которые могут его принять.

Замечание: когда пакет отбрасывается без отправки, Сервер может поместить этот отброшенный пакет в очередь мертвых писем (dead letter queue), или предпринять другие действия по диагностике. Такие действия выходят за рамки данной спецификации.

3.1.2.11.5. Topic Alias Maximum. 34 (0x22), идентификатор Topic Alias Maximum. За ним идет двухбайтное целое, представляющее значение Topic Alias Maximum. Если Topic Alias Maximum указано больше одного раза, то это Protocol Error. Если свойство Topic Alias Maximum отсутствует, то его значение по умолчанию 0.

Topic Alias Maximum показывает самое большое значение, которое Клиент будет принимать в качестве Topic Alias, отправленного Сервером. Клиент использует это значение, чтобы ограничить количество Topic Aliases, которое он будет удерживать на этом соединении. Сервер НЕ ДОЛЖЕН отправить Клиенту Topic Alias в пакете PUBLISH больше чем Topic Alias Maximum[MQTT-3.1.2-26]. Значение 0 показывает, что Клиент не принимает на этом соединении никакие Topic Alias. Если Topic Alias Maximum отсутствует или 0, то Сервер НЕ ДОЛЖЕН посылать Клиенту никакие Topic Alias[MQTT-3.1.2-27].

3.1.2.11.6. Request Response Information. 25 (0x19), идентификатор Request Response Information. За ним идет байт со значением 0 или 1. Если Request Response Information указано больше 1 раза, или если значение отличается от 0 или 1, то это Protocol Error. Если Request Response Information отсутствует, то используется значение 0.

Клиент использует это значение для запроса Серверу возвратить Response Information (информацию ответа) в CONNACK. Значение 0 показывает, что Сервер НЕ ДОЛЖЕН возвратить Response Information[MQTT-3.1.2-28]. Если значение 1, то Сервер МОЖЕТ возвратить Response Information в пакете CONNACK.

Замечание: Сервер может выбрать не включать Response Information в CONNACK, даже если Клиент запросил это.

См. секцию 4.10 для дополнительной информации про запрос / ответ (Request / Response).

3.1.2.11.7. Request Problem Information. 23 (0x17), идентификатор Request Problem Information. За ним идет байт со значением 0 или 1. Если Request Problem Information указано больше 1 раза, или если значение отличается от 0 или 1, то это Protocol Error. Если Request Problem Information отсутствует, то используется значение 1.

Клиент использует это значение, чтобы показать, отправляется ли Reason String или User Properties в случае сбоев.

Если значение Request Problem Information 0, то Сервер МОЖЕТ возвратить Reason String или User Properties в пакете CONNACK или DISCONNECT, но НЕ ДОЛЖЕН посылать Reason String или User Properties в любом пакете, кроме PUBLISH, CONNACK или DISCONNECT[MQTT-3.1.2-29]. Если это значение 0 и Клиент получил Reason String или User Properties в пакете, отличающемся от PUBLISH, CONNACK или DISCONNECT, то Клиент использует пакет DISCONNECT с Reason Code 0x82 (Protocol Error), как это описано в секции 4.13, посвященной обработке ошибок.

Если это значение 1, то Сервер МОЖЕТ возвратить Reason String или User Properties на любом пакете, для которого это разрешено.

3.1.2.11.8. User Property. 38 (0x26), идентификатор User Property, за которым идет пара строк (UTF-8 String Pair).

Свойству пользователя (User Property) разрешено появляться несколько раз, чтобы представлять несколько пар имя/значение. Одно и то же имя может появляться несколько раз.

Замечание: User Properties в пакете CONNECT могут использоваться для отправки от Клиента к Серверу свойств, относящихся к соединению. Смысл таких свойств не определен этой спецификацией.

3.1.2.11.9. Authentication Method. 21 (0x15), идентификатор метода аутентификации Authentication Method. За ним идет UTF-8 Encoded String, содержащая метод аутентификации, используемый для расширенной аутентификации. Если Authentication Method включен больш одного раза, то это Protocol Error.

Если Authentication Method отсутствует, то расширенная аутентификация не выполняется. См. секцию 4.12.

Если Клиент установит Authentication Method в CONNECT, то Клиент НЕ ДОЛЖЕН посылать любые пакеты, отличающиеся от AUTH или DISCONNECT, пока не получит пакет CONNACK[MQTT-3.1.2-30].

3.1.2.11.10. Authentication Data. 22 (0x16), идентификатор данных аутентификации. За ним идут двоичные данные (Binary Data), содержащие данные аутентификации. Если появились Authentication Data при отсутствии метода аутентификации, то это Protocol Error. Также Protocol Error, если Authentication Data появились больше одного раза.

Содержимое этих данных определяется методом аутентификации. См. секцию 4.12 для дополнительной информации по расширенной аутентификации.

3.1.2.12. Пример Variable Header.

  Описание 7 6 5 4 3 2 1 0
Имя протокола
Байт 1 MSB длины (0) 0 0 0 0 0 0 0 0
Байт 2 LSB длины (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 Версия (5) 0 0 0 0 0 1 0 1
Флаги соединения
Байт 8 User Name (1)
Password (1)
Will Retain (0)
Will QoS (01)
Will (1)
Clean Start (1)
Зарезервировано (0)
1 1 0 0 1 1 1 0
Keep Alive
Байт 9 MSB Keep Alive (0) 0 0 0 0 0 0 0 0
Байт 10 LSB Keep Alive (10) 0 0 0 0 1 0 1 0
Properties
Байт 11 Длина (5) 0 0 0 0 0 1 0 1
Байт 12 Идентификатор Session Expiry Interval (17) 0 0 0 1 0 0 0 1
Байт 13 Session Expiry Interval (10) 0 0 0 0 0 0 0 0
Байт 14 0 0 0 0 0 0 0 0
Байт 15 0 0 0 0 0 0 0 0
Байт 16 0 0 0 0 1 0 1 0

Рис. 3‑6. Пример содержимого Variable Header.

3.1.3. CONNECT Payload. Полезная нагрузка (Payload) пакета CONNECT содержит одно или большее количество полей с префиксом длины, наличие которых определяется флагами в Variable Header. Эти поля, если присутствуют, ДОЛЖНЫ появлятся в порядке Client Identifier (идентификатор Клиента), Will Properties, Will Topic, Will Payload, User Name, Password[MQTT-3.1.3-1].

3.1.3.1. Client Identifier (ClientID). Поле ClientID идентифицирует Клиента для Сервера. Каждый Клиент, подключающийся к Серверу, имеет уникальный ClientID. ClientID ДОЛЖЕН использоваться Клиентами и Серверами для идентификации состояния, которое они хранят в контексте MQTT-сессии между Клиентом и Сервером[MQTT-3.1.3-2]. См. секцию 4.1 для дополнительной информации по состоянию сессии (Session State).

ClientID ДОЛЖЕН присутствовать, и это должно быть первое поле в полезной нагрузке (Payload) пакета CONNECT[MQTT-3.1.3-3].

ClientID ДОЛЖЕН быть в формате UTF-8 Encoded String, как это определено выше в секции 1.5.4[MQTT-3.1.3-4].

Сервер ДОЛЖЕН дозволять идентификаторы ClientID линой от 1 до 23 байт UTF-8, и в которых могут содержаться только символы "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"[MQTT-3.1.3-5].

Сервер МОЖЕТ дозволять идентификаторы ClientID, которые содержать больше 23 закодированных байт. Сервер МОЖЕТ дозволять ClientID с символами, которые не включены в вышеуказанный список.

Сервер МОЖЕТ дозволять Клиенту предоставлять ClientID, длина которых равна 0 байт, однако в таком раскладе Сервер ДОЛЖЕН обрабатывать этот случай как специальный, и назначать для Клиента уникальный ClientID[MQTT-3.1.3-6]. Он ДОЛЖЕН затем обработать пакет CONNECT как если бы Клиент предоставил этот уникальный ClientID, и ДОЛЖЕН возвратить назначенный идентификатор Клиента (Assigned Client Identifier) в пакете CONNACK[MQTT-3.1.3-7].

Если Сервер отклонил ClientID, то он МОЖЕТ ответить пакетом CONNECT с CONNACK, используя Reason Code 0x85 (Client Identifier not valid), как это описано в секции 4.13 обработки ошибок, и затем Сервер ДОЛЖЕН закрыть сетевое соединение[MQTT-3.1.3-8].

Замечание: реализация Клиента может предоставить удобный метод для генерации случайного ClientID. Клиенты, использующие такой метод, должны избегать создания долгоживущих осиротевших сессий.

3.1.3.2. Will Properties. Если Will Flag установлен в 1, то Will Properties должно быть следующим полем в Payload. Поле Will Properties определяет свойства Application Message для отправки с Will Message, когда оно опубликовано, и свойства, которые определяют, когда публиковать Will Message. Will Properties состоит из длины свойств (Property Length) и самих свойств (Properties).

3.1.3.2.1. Property Length. Длина свойств в Will Properties, закодированная как Variable Byte Integer.

3.1.3.2.2. Will Delay Interval. 24 (0x18), идентификатор Will Delay Interval. За ним идет четырехбайтное целое, представляющее Will Delay Interval в секундах. Если Will Delay Interval подключен больше одного раза, то это Protocol Error. Если Will Delay Interval отсутствует, то его значение по умолчанию 0, и тогда нет задержки перед публикацией Will Message.

Сервер задерживает публикацию Will Message Клиента, пока не завершится переданный Will Delay Interval, в зависимости от того, что произойдет первым. Если новое сетевое соединение для этой сессии было сделано до того, как был передан Will Delay Interval, то Сервер НЕ ДОЛЖЕН посылать Will Message[MQTT-3.1.3-9].

Замечания:

1. Одно из использований этой функции - избежать публикации Will Message, если произошло временное отключение сети, и Клиент успешно подключился заново и продолжает свою сессию до публикации Will Message.

2. Если сетевое соединение использует идентификатор Клиента на существующем сетевом соединении с Сервером, то Will Message для существующего соединения отправляется, если новое соединение не указывает Clean Start 0, и Will Delay больше 0. Если Will Delay 0, то Will Message отправляется на закрытии существующего сетевого соединения, и если Clean Start 1, то Will Message отправиться по причине завершения сессии.

3.1.3.2.3. Payload Format Indicator. 1 (0x01), идентификатор формата полезной нагрузки (Payload Format Indicator). За ним идет байт в одном из следующих значений:

0 (0x00) показывает, что Will Message это не указанные байты, что эквивалентно не отправке Payload Format Indicator.
1 (0x01) показывает, что Will Message содержит UTF-8 Encoded Character Data. Данные UTF-8 в Payload ДОЛЖНЫ быть правильно сформированным UTF-8, как это определено спецификацией Unicode, и заново сформулировано в RFC 3629 [RFC3629].

Если Payload Format Indicator подключен больше одного раза то это Protocol Error. Сервер МОЖЕТ проверить Will Message на предмет индикации формата, и может отправить CONNACK с Reason Code 0x99 (Payload format invalid), как это описано в секции 4.13.

3.1.3.2.4. Message Expiry Interval. 2 (0x02), идентификатор Message Expiry Interval. За ним идет 4-байтное целое, представляющее Message Expiry Interval. Если Message Expiry Interval подключен более 1 раза, то это Protocol Error.

Это 4-байтное значение, которое если присутствует, то указывает время жизни Will Message в секундах, и отправляется как Publication Expiry Interval, когда Сервер публикует Will Message.

Если отсутствует, то Message Expiry Interval не отправляется, когда Сервер публикует Will Message.

3.1.3.2.5. Content Type. 3 (0x03), идентификатор типа содержимого (Content Type). За ним идет строка в формате UTF-8 Encoded String, описывающая содержимое Will Message. Если Content Type появляется больше одного раза, то это Protocol Error. Значение Content Type определяется отправляющим и принимающим сообщение приложением.

3.1.3.2.6. Response Topic. 8 (0x08), идентификатора темы ответа (Response Topic). За ним идет строка в формате UTF-8 Encoded String, которая используется как Topic Name для сообщения ответа. Если Response Topic подключен более одного раза, то это Protocol Error. Наличие Response Topic идентифицирует Will Message как Request.

См. секцию 4.10 для дополнительной информации по запросу/ответу (Request / Response).

3.1.3.2.7. Correlation Data. 9 (0x09), идентификатор данных корреляции. За ним идут двоичные данные (Binary Data). Correlation Data используются отправителем Request Message для идентификации того, какой запрос является ответным (Response Message) при его получении. Если Correlation Data подключены больше одного раза, то это Protocol Error. Если Correlation Data не представлены, то запрашивающему (Requester) не нужны никакие данные корреляции.

Значение Correlation Data имеет смысл только для отправителя Request Message и получателя Response Message.

См. секцию 4.10 для дополнительной информации по запросу/ответу (Request / Response).

3.1.3.2.8. User Property. 38 (0x26), идентификатор свойства пользователя, за которым идет UTF-8 String Pair. User Property может появляться несколько раз для представления нескольких пар имя/значение. Одно и то же имя может также появляться больше одного раза.

Сервер ДОЛЖЕН придерживаться порядка следования User Properties, когда публикует Will Message[MQTT-3.1.3-10].

Замечание: это свойство предназначено для предоставления способа передачи тэгов имя-значение (name-value), смысл которых и интерпретация известна только программам приложения, которые их посылают и принимают.

3.1.3.3. Will Topic. Если Will Flag установлен в 1, то Will Topic следующее поле в Payload. Will Topic ДОЛЖЕН быть UTF-8 Encoded String, как это описано в секции 1.5.4[MQTT-3.1.3-11].

3.1.3.4. Will Payload. Если Will Flag установлен в 1, то Will Payload следующее поле в Payload. Will Payload определяет полезную нагрузку сообщения приложения (Application Message Payload), которая публикуется в Will Topic, как описано в секции 3.1.2.5. Это поле состоит из двоичных данных (Binary Data).

3.1.3.5. User Name. Если User Name Flag установлен в 1, то User Name следующее поле в Payload. User Name ДОЛЖНО быть UTF-8 Encoded String, как это определено в секции 1.5.4[MQTT-3.1.3-12]. Это может использоваться Сервером для аутентификации и авторизации.

3.1.3.6. Password. Если Password Flag установлен в 1, то Password следующее поле в Payload. Поле Password это двоичные данные (Binary Data). Хотя это поле называется Password, оно может использоваться для переноса любой учетной информации.

3.1.4. CONNECT Actions. Обратите внимание, что Сервер МОЖЕТ поддерживать несколько протоколов, включая протокол MQTT другой версии на том же самом порту TCP или другой конечной точки сети. Если Сервер определит, что протокол MQTT v5.0, то по этому протоколу будут проверяться последующие попытки соединения.

1. Если Сервер не принял пакет CONNECT в течение разумного времени после установки сетевого соединения, Сервер ДОЛЖЕН закрыть сетевое соединение.

2. Сервер ДОЛЖЕН проверить, что пакет CONNECT соответствует формату, описанному в секции 3.1, и закрыть сетевое соединение, если обнаружит несоответствие[MQTT-3.1.4-1]. Сервер МОЖЕТ отправить CONNACK с Reason Code 0x80 или больше, как описано в секции 4.13 перед закрытием сетевого соединения.

3. Сервер МОЖЕТ проверить содержимое пакета CONNECT, что он удовлетворяет любым дополнительным ограничениям, и ДОЛЖЕН выполнить проверки аутентификации и авторизации. Если любая из этих проверок завершилась неудачей, то Сервер ДОЛЖЕН закрыть сетевое соединение[MQTT-3.1.4-2]. Перед закрытием сетевого соединения Сервер МОЖЕТ отправить подходящий CONNACK-ответ с Reason Code 0x80 или больше, как это описано в секции 3.2 и секции 4.13.

Если проверка успешная, то Сервер выполняет следующие шаги.

1. Если ClientID представляет Клиента, который уже подключен к Серверу, то Сервер отправит пакет DISCONNECT существующему Клиенту с Reason Code 0x8E (Session taken over), как это описано в секции 4.13, и ДОЛЖЕН закрыть сетевое соединение существующего Клиента [MQTT-3.1.4-3]. Если у существующего Клиента есть Will Message, то Will Message публикуется, как описано в секции 3.1.2.5.

Замечание: если Will Delay Interval существующего сетевого соединения 0, и есть Will Message, то оно будет отправлено, потому что сетевое соединение закрыто. Если Session Expiry Interval существующего сетевого соединения 0, или у нового сетевого соединения Clean Start установлен в 1, то если у существующего сетевого соединения есть Will Message, то оно будет отправлено, потому предыдущая сессия была завершена при поглощении.

2. Сервер ДОЛЖЕН выполнить обработку Clean Start, как описано в секции 3.1.2.4[MQTT-3.1.4-4].

3. Сервер ДОЛЖЕН подтвердить пакет CONNECT пакетом CONNACK, содержащим 0x00 (Success) Reason Code[MQTT-3.1.4-5].

Замечание: рекомендуется выполнить проверки аутентификации и авторизации, если Сервер используется для обработки критических бизнес-данных в любой форме. Если эти проверки прошли успешно, то Сервер отвечает отправкой CONNACK с Reason Code 0x00 (Success). Если проверка не прошла, то рекомендуется, чтобы Сервер не посылал вообще CONNACK, поскольку такая отправка предупреждает потенциального атакующего о наличии в сети активного Сервера MQTT, и приглашает тем самым выполнить DoS-атаку, или атаку подбора/запроса пароля.

4. Запуск доставки сообщения и мониторинга Keep Alive.

Клиентам разрешается отправлять дополнительные MQTT Control Packets сразу после отправки пакета CONNECT; Клиентам не надо ждать поступления пакета CONNACK от Сервера. Если Сервер отклонил CONNECT, то он НЕ ДОЛЖЕН обрабатывать любые данные, посланные Клиентом после пакета CONNECT, за исключением пакета AUTH[MQTT-3.1.4-6].

Замечания:

- Клиенты обычно ждут пакета CONNACK. Однако если Клиент эксплуатирует возможность отправки MQTT Control Packets до момента получения CONNACK, то реализацию Клиента можно упростить, поскольку не нужно контролировать состояние соединения. Клиент понимает, что любые данные, которые он послал до приема пакета CONNACK, не будут обработаны, если Сервер отклонил соединение.
- Клиенты, которые послали MQTT Control Packets до приема CONNACK, не будут знать об ограничениях Сервера, и о том, используется ли какая-либо существующая сессия.
- Сервер может ограничить чтение из сетевого соединения, или закрыть сетевое соединение, если Клиент послал слишком много данных перед завершением аутентификации. Это рекомендуется как способ избежать атак типа отказ-от-обслуживания (DoS).

3.2. CONNACK – Connect acknowledgement. CONNACK это пакет, отправляемый Сервером в ответ на пакет CONNECT, полученный от Клиента. Сервер ДОЛЖЕН отправить CONNACK с Reason Code 0x00 (Success) перед отправкой любого пакета, отличающегося от AUTH[MQTT-3.2.0-1]. Сервер НЕ ДОЛЖЕН посылать больше одного CONNACK на сетевое соединение[MQTT-3.2.0-2].

Если Клиент не получил пакет CONNACK от Сервера за разумное время, то Клиент ДОЛЖЕН закрыть сетевое соединение. "Разумное" количество времени зависит от типа приложения и инфраструктуры коммуникаций.

3.2.1. CONNACK Fixed Header. Формат фиксированного заголовка иллюстрируется рисунком 3-7.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (2) Зарезервировано
  0 0 1 0 0 0 0 0
Байт 2 Remaining Length

Рис. 3‑7. Фиксированный заголовок пакета CONNACK.

Remaining Length. Это поле указывает длину Variable Header, закодированного как Variable Byte Integer.

3.2.2. CONNACK Variable Header. Variable Header пакета CONNACK содержит следующие поля в таком порядке: Connect Acknowledge Flags (флаги подтверждения коннекта), Connect Reason Code (код причины соединения) и Properties (свойства). Правила кодирования свойств описаны в секции 2.2.2.

3.2.2.1. Connect Acknowledge Flags. Байт 1 это "флаги подтверждения соединения". Биты 7-1 зарезервированы, и ДОЛЖНЫ быть установлены в 0[MQTT-3.2.2-1].

Бит 0 это флаг наличия сессии (Session Present).

3.2.2.1.1. Session Present, флаг наличия сессии. Флаг TSession Present информирует Клиента, использует ли Сервер состояние сессии (Session State) из предыдущего соединения для этого ClientID. Это позволяет Клиенту и Серверу получить согласованное представление о Session State.

Если Сервер принял соединение с Clean Start, установленным в 1, то Сервер ДОЛЖЕН установить Session Present в 0 пакета CONNACK в дополнение к установке 0x00 (Success) Reason Code пакета CONNACK[MQTT-3.2.2-2].

Если Сервер принял соединение Клиента с Clean Start, установленным в 0, и у Сервера есть Session State для ClientID, полученном в запросе соединения, то Сервер ДОЛЖЕН установить Session Present в 1 пакета CONNACK, иначе он ДОЛЖЕН установить Session Present в 0. В обоих случаях Сервер ДОЛЖЕН установить 0x00 (Success) Reason Code в пакете CONNACK[MQTT-3.2.2-3].

Если значение Session Present, принятое Клиентом от Сервера, неожиданное, то Клиент делает следующее:

· Если у Клиента нет Session State, и он получает Session Present, установленный в 1, то он ДОЛЖЕН закрыть сетевое соединение[MQTT-3.2.2-4]. Если Клиент хочет сделать рестарт с новой сессией, то он может выполнить реконнект с использованием Clean Start, установленного в 1.
· Если у Клиента есть Session State, и он принял Session Present, установленный в 0, то Клиент ДОЛЖЕН отбросить свое Session State, если он продолжает работать с сетевым соединением[MQTT-3.2.2-5].

Если Сервер посылает пакет CONNACK, содержащий ненулевой Reason Code, то он ДОЛЖЕН установить Session Present в 0[MQTT-3.2.2-6].

3.2.2.2. Connect Reason Code. Байт 2 в Variable Header это Connect Reason Code, его значения показаны в таблице ниже. Если Сервером принят правильно сформированный пакет CONNECT, но Сервер не может завершить соединение, то Сервер МОЖЕТ послать пакет CONNACK, содержащий подходящий код Connect Reason из этой таблицы. Если Сервер отправил пакет CONNACK, содержащий Reason Code 128 или больше, то он ДОЛЖЕН закрыть сетевое соединение[MQTT-3.2.2-7].

Таблица 3‑1. Значения Connect Reason Code.

Dec Hex Имя Reason Code
Описание
0 0x00 Успешное завершение Соединение принято.
128 0x80 Неопределенная ошибка Сервер не хочет раскрыть причину отказа, или не подходит никакой из других Reason Code.
129 0x81 Malformed Packet Данные в пакете CONNECT не могут быть корректно обработаны.
130 0x82 Protocol Error Данные в пакете CONNECT не удовлетворяют этой спецификации.
131 0x83 Ошибка, специфичная для реализации Пакет CONNECT сформирован корректно, но он не может быть принят этим Сервером.
132 0x84 Не поддерживаемая версия протокола Сервер не поддерживает версию протокола, которую запросил клиент.
133 0x85 Недопустимый идентификатор клиента Идентификатор клиента - нормальная строка, однако она недопустима для Сервера.
134 0x86 Ошибка User Name или Password Сервер не принял имя пользователя или пароль, предоставленные Клиентом.
135 0x87 Не авторизовано Клиент не авторизован для соединения.
136 0x88 Сервер недоступен Сервер MQTT недоступен.
137 0x89 Сервер занят Сервер занят, попробуйте подключиться позже.
138 0x8A Banned Этот Клиент заблокирован административными действиями. Свяжитесь с администратором сервера.
140 0x8C Неправильный метод аутентификации Метод аутентификации не поддерживается, или не соответствует используемому в настоящий момент методу.
144 0x90 Недопустимое Topic Name Will Topic Name сформировано корректно, но оно не может быть принято этим Сервером.
149 0x95 Пакет слишком большой Размер пакета CONNECT превысил допустимое значение.
151 0x97 Превышена квота Превышение реализации, или превышен установленный административно предел.
153 0x99 Недопустимый формат полезной нагрузки Will Payload не соответствует указанному Payload Format Indicator.
154 0x9A Retain не поддерживается Сервер не поддерживает сохраненные сообщения, и Will Retain был установлен в 1.
155 0x9B QoS не поддерживается Сервер не поддерживает QoS, установленное в Will QoS.
156 0x9C Используйте другой сервер Клиент временно должен использовать другой Сервер.
157 0x9D Сервер перемещен Клиент должен постоянно использовать другой Сервер.
159 0x9F Превышена частота подключений Превышен лимит частоты подключений.

Сервер при отправке пакета CONNACK ДОЛЖЕН использовать одно из значений Connect Reason Code[MQTT-3.2.2-8].

Замечания:

1. Reason Code 0x80 (Unspecified error) может использоваться, когда Сервер знает о причине сбоя, однако не хочет раскрыть её для Клиента, или когда неприменимо ни одно из значений Reason Code таблицы 3-1.

2. Сервер может выбрать закрыть сетевое соединение без отправки CONNACK, чтобы улучшить безопасность для случая, когда с пакетом CONNECT найдена ошибка. Например, когда публичная сеть и соединение не авторизованы, может быть нежелательным показывать, что это Сервер MQTT.

3.2.2.3. CONNACK Properties.

3.2.2.3.1. Property Length. Это длина свойств (Properties) в Variable Header пакета CONNACK, закодированная как Variable Byte Integer.

3.2.2.3.2. Session Expiry Interval. 17 (0x11), идентификатор интервала времени жизни сессии (Session Expiry Interval). За ним идет 4-байтное целое, представляющее интервал истечения времени сессии в секундах. Если Session Expiry Interval подключен больше одного раза, то это Protocol Error.

Если Session Expiry Interval отсутствует, то используется значение в пакете CONNECT. Сервер использует это свойство для информирования Клиента, что используется значение, отличающееся от того, что послал Клиент. См. секцию 3.1.2.11.2 для описания использования Session Expiry Interval.

3.2.2.3.3. Receive Maximum. 33 (0x21), идентификатор Receive Maximum, за которым идет двухбайтное значение, представляющее принимаемый максимум. Если Receive Maximum подключено больше одного раза, или имеет значение 0, то это Protocol Error.

Сервер использует это значение для ограничения количества публикаций QoS 1 и QoS 2, которые будут конкурентно обрабатываться для Клиента. Не предоставляется механизм ограничения публикаций QoS 0, которые может попытаться отправить Клиент.

Если значение Receive Maximum отсутствует, то принимается значение по умолчанию 65535.

См. секцию 4.9 с описанием управления потоком для подробностей по использованию Receive Maximum.

3.2.2.3.4. Maximum QoS. 36 (0x24), идентификатор максимального QoS. За ним идет байт со значением 0 или 1. Если Maximum QoS подключено больше одного раза, или имеет значение, отличающееся от 0 или 1, то это Protocol Error. Если Maximum QoS отсутствует, то Клиент использует Maximum QoS 2.

Если Сервер не поддерживает QoS1 или QoS2 пакетов PUBLISH, то он ДОЛЖЕН отправить Maximum QoS в пакете CONNACK с указанием самого высшего QoS, которое он поддерживает[MQTT-3.2.2-9]. Сервер, который не поддерживает пакеты PUBLISH QoS 1 или QoS 2, ДОЛЖЕН принимать пакеты SUBSCRIBE, содержащие Requested QoS0, QoS1 или QoS2[MQTT-3.2.2-10].

Если Клиент получил Maximum QoS от Сервера, то он НЕ ДОЛЖЕН посылать пакеты PUBLISH с уровнем QoS, превышающим указанный уровень Maximum QoS[MQTT-3.2.2-11]. Если Сервер принимает пакет PUBLISH с QoS, больше указанного Maximum QoS, то это ошибка Protocol Error. В этом случае используется DISCONNECT с Reason Code 0x9B (QoS not supported), как описано в секции 4.13 обработки ошибок.

Если Сервер принимает пакет CONNECT, содержащий Will QoS, который превышает возможности Сервера, то он ДОЛЖЕН отклонить соединение. Он ДОЛЖЕН использовать пакет CONNACK с Reason Code 0x9B (QoS not supported), как описано в секции 4.13 обработки ошибок, и ДОЛЖЕН закрыть сетевое соединение[MQTT-3.2.2-12].

Замечание: Клиенту не нужно поддерживать пакеты PUBLISH QoS 1 или QoS 2. Если это тот случай, то Клиент просто ограничивает поле максимума QoS в любой команде SUBSCRIBE, он посылает значение, которое может поддержать.

3.2.2.3.5. Retain Available. 37 (0x25), идентификатор Retain Available.

За ним идет поле Byte. Если свойство присутствует, то этот байт декларирует, поддерживает ли Сервер сохраненные сообщения (retained messages). Значение 0 показывает, что сохраненные сообщения не поддерживаются. Значение 1 показывает, что сохранные сообщения поддерживаются. Если свойство отсутствует, то retained messages поддерживается. Если свойство указано больше одного раза, или его значение отличается от 0 или 1, то это Protocol Error.

Если Сервер получил пакет CONNECT, содержащий Will Message, где Will Retain установлено в 1, и Сервер не поддерживает retained messages, то Сервер ДОЛЖЕН отклонить запрос на соединение. Он ДОЛЖЕН послать CONNACK с Reason Code 0x9A (Retain not supported), затем ДОЛЖЕН закрыть сетевое соединение[MQTT-3.2.2-13].

Клиент, получивший Retain Available, установленный в 0 от Сервера, НЕ ДОЛЖЕН посылать пакет PUBLISH с флагом RETAIN, установленным в 1[MQTT-3.2.2-14]. Если Сервер получил такой пакет, то это Protocol Error. Сервер может МОЖЕТ послать DISCONNECT с Reason Code 0x9A (Retain not supported), как описано в секции 4.13.

3.2.2.3.6. Maximum Packet Size. 39 (0x27), идентификатор Maximum Packet Size.

За ним идет 4-байтное целое, представляющее максимальный размер пакета, который Сервер примет. Если Maximum Packet Size не представлен, то нет никаких ограничений на размер пакета в пределах ограничений протокола в результате кодирования оставшейся длины и размеров заголовка протокола.

Если свойство Maximum Packet Size указано больше одного раза, или его значение установлено в 0, то это Protocol Error.

Размер пакета это общее количество байт в MQTT Control Packet, как это определено в секции 2.1.4. Сервер использует Maximum Packet Size, чтобы информировать Клиента, что Сервер не будет обрабатывать пакеты, размер которых превышает этот лимит.

Клиент НЕ ДОЛЖЕН посылать Серверу пакеты, превышающие по длине Maximum Packet Size[MQTT-3.2.2-15]. Если Сервер получит пакет который по размеру превышает этот лимит, то это Protocol Error, Сервер использует DISCONNECT с Reason Code 0x95 (Packet too large), как описано в секции 4.13.

3.2.2.3.7. Assigned Client Identifier. 18 (0x12), идентификатор Assigned Client Identifier.

За ним идет строка UTF-8, которая представляет Assigned Client Identifier, назначенный идентификатор Клиента. Если свойство Assigned Client Identifier указано больше одного раза, то это Protocol Error.

Это идентификатор Клиента, который был назначен Сервером, потому что в пакете CONNECT был найден идентификатор Клиента нулевой длины (Клиент не назначил себе идентификатор).

Если Клиент подключается с идентификатором Клиента нулевой длины, то Сервер ДОЛЖЕН ответить CONNACK, в котором содержится Assigned Client Identifier. Этот назначенный идентификатор Клиента ДОЛЖЕН быть новым идентификатором, который не используется любой другой сессией, находящейся в настоящий момент на Сервере[MQTT-3.2.2-16].

3.2.2.3.8. Topic Alias Maximum. 34 (0x22), идентификатор Topic Alias Maximum.

За ним идет 2-байтное целое, представляющее максимальное значение псевдонима темы (Topic Alias Maximum). Если свойство Topic Alias Maximum указано больше одного раза, то это Protocol Error. Если Topic Alias Maximum отсутствует, то его значение по умолчанию 0.

Это значение показывает самое большое значение, которое Сервер примет в качестве псевдонима темы (Topic Alias), отправленного Клиентом. Сервер использует это значение для ограничения числа псевдонимов тем, которое он хранит на этом соединении. Клиент НЕ ДОЛЖЕН посылать Topic Alias Серверу в пакете PUBLISH больше, чем это значение[MQTT-3.2.2-17]. Значение 0 показывает, что Сервер не принимате никакие псевдонимы тем на этом соединении. Если Topic Alias Maximum отсутствует или 0, то Клиент НЕ ДОЛЖЕН посылать никакие Topic Alias Серверу[MQTT-3.2.2-18].

3.2.2.3.9. Reason String. 31 (0x1F), идентификатор Reason String.

За ним идет строка UTF-8 Encoded String, представляющая причину, связанную с этим ответом. Эта Reason String является строкой, удобной для чтения человеком, она разработана для диагностики, и она НЕОБЯЗАТЕЛЬНО ДОЛЖНА быть обработана Клиентом.

Сервер использует это значение, чтобы предоставить Клиенту дополнительную информацию. Сервер НЕ ДОЛЖЕН посылать это свойство, если он увеличит пакет CONNACK сверх Maximum Packet Size, указанного Клиентом [MQTT-3.2.2-19]. Если Reason String указано больше одного раза, то это Protocol Error.

Замечание: правильное использование reason string в Клиенте - подключить эту информацию в сообщение исключения, выбрасываемое кодом Клиента по ошибке, или запись этой строки в лог диагностики.

3.2.2.3.10. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной информации Клиенту, включая информацию диагностики. Сервер НЕ ДОЛЖЕН посылать это свойство, если оно приведет к увеличению размера пакета CONNACK свыше Maximum Packet Size, указанного Клиентом[MQTT-3.2.2-20]. Для User Property разрешено появляться несколько раз, чтобы представить несколько пар имя-значение (name-value). Одно и то же имя может появляться больше одного раза.

Содержимое и смысл свойства User Property не опредено этой спецификацией. Получатель пакета CONNACK, в котором содержится User Property, МОЖЕТ игнорировать его содержимое.

3.2.2.3.11. Wildcard Subscription Available. 40 (0x28), идентификатор Wildcard Subscription Available.

За ним идет поле Byte. Если свойство присутствует, то этот байт декларирует, поддерживает ли Сервер подписки с символами множественной макроподстановки (Wildcard Subscriptions). Значение 0 показывает, что Wildcard Subscriptions не поддерживаются. Значение 1 показывает, что Wildcard Subscriptions поддерживаются. Если свойство отсутствует, то Wildcard Subscriptions поддерживаются. Если Wildcard Subscription Available указано больше одного раза, или его значение отличается от 0 или 1, то это Protocol Error.

Если Сервер получил пакет SUBSCRIBE, содержащий Wildcard Subscription, и Сервер не поддерживает Wildcard Subscriptions, то это Protocol Error. Сервер использует DISCONNECT с Reason Code 0xA2 (Wildcard Subscriptions not supported), как описано в секции 4.13.

Если Сервер поддерживает Wildcard Subscriptions, то он все еще может отклонить определенный запрос на подписку, содержащий Wildcard Subscription. В этом случае Сервер МОЖЕТ послать SUBACK Control Packet с Reason Code 0xA2 (Wildcard Subscriptions not supported).

3.2.2.3.12. Subscription Identifiers Available. 41 (0x29), идентификатор Subscription Identifier Available.

За ним идет поле Byte. Если свойство присутствует, то этот байт декларирует, поддерживает ли Сервер идентификаторы подписки (Subscription Identifiers). Значение 0 показывает, что Subscription Identifiers не поддерживаются. Значение 1 показывает, что Subscription Identifiers поддерживаются. Если свойство отсутствует, то Subscription Identifiers поддерживаются. Если Subscription Identifier Available указано больше одного раза, или его значение отличается от 0 или 1, то это Protocol Error.

Если Сервер получил пакет SUBSCRIBE, содержащий Subscription Identifier, и Сервер не поддерживает идентификаторы подписки, то это Protocol Error. Сервер использует DISCONNECT с Reason Code 0xA1 (Subscription Identifiers not supported), как описано в секции 4.13.

3.2.2.3.13. Shared Subscription Available. 42 (0x2A), идентификатор Shared Subscription Available.

За ним идет поле Byte. Если свойство присутствует, то этот байт декларирует, поддерживает ли Сервер общие подписки (Shared Subscriptions). Значение 0 показывает, что Shared Subscriptions не поддерживаются. Значение 1 показывает, что Shared Subscriptions поддерживаются. Если свойство отсутствует, то Shared Subscriptions поддерживаются. Если Shared Subscription Available указано больше одного раза, или его значение отличается от 0 или 1, то это Protocol Error.

Если Сервер получил пакет SUBSCRIBE, содержащий Shared Subscriptions, и Сервер не поддерживает общие подписки, то это Protocol Error. Сервер использует DISCONNECT с Reason Code 0x9E (Shared Subscriptions not supported), как описано в секции 4.13.

3.2.2.3.14. Server Keep Alive. 19 (0x13), идентификатор Server Keep Alive.

За ним идет 2-байтовое целое с временем жизни соединения (Keep Alive time), назначенное Сервером. Если Сервер посылает Server Keep Alive в пакете CONNACK, то Клиент ДОЛЖЕН использовать это значение вместо значение Keep Alive, которое Клиент послал в пакете CONNECT[MQTT-3.2.2-21]. Если Сервер не послал Server Keep Alive, то Сервер ДОЛЖЕН использовать значение Keep Alive, установленное Клиентом в пакете CONNECT[MQTT-3.2.2-22]. Если Server Keep Alive указано больше одного раза, то это Protocol Error.

Замечание: основное использование Server Keep Alive для Сервера - проинформировать Клиента, что Сервер будет отключать Клиента, если отсутствие активности Клиента будет продолжаться так долго, что приблизилось к времени Keep Alive.

3.2.2.3.15. Response Information. 26 (0x1A), идентификатор Response Information.

За ним идет строка UTF-8 Encoded String, которая используется в качестве базиса для создания темы ответа (Response Topic). Способ, которым Клиент создает Response Topic из Response Information, не определяется этой спецификацией. Если Response Information указано больше одного раза, то это Protocol Error.

Если Клиент посылает Request Response Information со значением 1, то для Сервера НЕ ОБЯЗАТЕЛЬНО посылать Response Information в пакете CONNACK.

Замечание: общее использование Response Information - передать глобально уникальную порцию дерева тем (topic tree), которая зарезервирована для этого Клиента на как минимум время жизни его сессии. Это часто не может быть просто случайным именем, так как и запрашивающий Клиент, и отвечающий Клиент должны быть авторизованы для его использования. Обычно это используется в качестве корня дерева тем для конкретного Клиента. Чтобы Сервер возвращал эту информацию, он обычно должен быть корректно сконфигурирован. Использование этого механизма позволяет этой конфигурации быть сделанной только один раз на Сервере, вместо того, чтобы конфигурировать это для каждого Клиента.

См. секцию 4.10 для дополнительной информации по запросу/ответу (Request / Response).

3.2.2.3.16. Server Reference. 28 (0x1C), идентификатор Server Reference.

За ним идет строка UTF-8 Encoded String, которая может использоваться Клиентом для идентификации другого используемого Сервера. Если Server Reference указано больше одного раза, то это Protocol Error.

Сервер использует Server Reference либо в пакете CONNACK, либо в пакете DISCONNECT, с Reason Code 0x9C (Use another server), или Reason Code 0x9D (Server moved), как описано в секции 4.13.

См. секцию 4.11 с описанием перенаправления на Сервер для дополнительной информации о том, как используется Server Reference.

3.2.2.3.17. Authentication Method. 21 (0x15), идентификатор Authentication Method.

За ним идет строка UTF-8 Encoded String, содержащая имя метода аутентификации. Если Authentication Method указано больше одного раза, то это Protocol Error. См. секцию 4.12 для дополнительной информации о расширенной идентификации.

3.2.2.3.18. Authentication Data. 22 (0x16), идентификатор Authentication Data.

За ним идут двоичные данные (Binary Data), где содержатся данные аутентификации. Содержимое этих данных опрпеделяется методом аутентификации и состоянием уже прошедшего обмена данными аутентификации. Если Authentication Data указано больше одного раза, то это Protocol Error. См. секцию 4.12 для дополнительной информации о расширенной идентификации.

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

3.3. PUBLISH – Publish message. Пакет PUBLISH посылается от Клиента Серверу или от Сервера Клиенту для транспортировки Application Message.

3.3.1. PUBLISH Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (3) Флаг DUP Уровень QoS RETAIN
  0 0 1 1 X X X X
Байт 2... Remaining Length

Рис. 3‑8. Fixed Header пакета PUBLISH.

3.3.1.1. DUP. Позиция: байт 1, бит 3.

Если флаг DUP установлен в 0, то это показывает, что Клиент или Сервер впервые попытались послать этот пакет PUBLISH. Если флаг DUP установлен в 1, то это показывае возможную повторную доставку более ранней попытки отправки пакета.

Флаг DUP ДОЛЖЕН быть установлен в 1 Клиентом или Сервером, когда они пытаются повторно доставить пакет PUBLISH[MQTT-3.3.1-1]. Флаг DUP ДОЛЖЕН быть установлен в 0 для всех сообщений QoS0[MQTT-3.3.1-2].

Значение флага DUP из поступившего пакета PUBLISH не распространяется, когда пакет PUBLISH рассылается Сервером для подписчиков. Флаг DUP в исходящем пакете устанавливается независимо от пришедшего пакета PUBLISH, значение этого флага ДОЛЖНО полностью определяться тем, происходит ли ретрансмиссия исходящего пакета PUBLISH [MQTT-3.3.1-3].

Замечания:

1. Получатель MQTT Control Packet, котором флаг DUP установлен в 1, не может подразумевать, что он видит предыдущую копию этого пакета.
2. Важно отметить, что флаг DUP относится к самому MQTT Control Packet, но не к Application Message, которое содержится в пакете. Когда используется QoS1, то возможно для Клиента получить пакет PUBLISH с флагом DUP, установленным в 0, и в пакете содержится повтор Application Message, которое было принято ранее, но Packet Identifier другой. Секция 2.2.1 предоставляет больше информации об идентификаторах пакета.

3.3.1.2. QoS. Позиция: байт 1, биты 2-1.

Это поле показывает уровень гарантии доставки Application Message. Уровни QoS показаны ниже.

Таблица 3‑2. Определения уровней QoS.

Значение QoS Бит 2 Бит 1 Описание
0 0 0 Доставка не более одного раза
1 0 1 Доставка по крайней мере 1 раз
2 1 0 Доставка точно 1 раз
- 1 1 Зарезервировано - нельзя использовать

Если Сервер подключил Maximum QoS в своем ответе CONNACK для Клиента, и получил пакет PUBLISH с QoS больше, чем был в CONNACK, то Сервер использует DISCONNECT с Reason Code 0x9B (QoS not supported), как описано в секции 4.13 по обработке ошибок.

Пакет PUBLISH НЕ ДОЛЖЕН иметь оба бита QoS, установленные в 1[MQTT-3.3.1-4]. Если Сервер или Клиент получили пакет PUBLISH, у которого в поле QoS установлены в 1 оба бита, то это Malformed Packet. Используйте DISCONNECT с Reason Code 0x81 (Malformed Packet), как описано в секции 4.13.

3.3.1.3. RETAIN. Позиция: байт 1, бит 0.

Если флаг RETAIN устанавлен в 1 в пакете PUBLISH, который Клиент отправил Серверу, то Сервер ДОЛЖЕН заменить любое существующее сохраненное сообщение (retained message) для этой темы (topic), и сохранить Application Message[MQTT-3.3.1-5], так чтобы оно могло быть доставлено будущим подписчикам, подписки которых соответствуют имени темы (Topic Name) сообщения. Если Payload содержит 0 байт, это будет нормально будет обработано Сервером, но при этом любое сохраненное сообщение (retained message) с таким же именем темы ДОЛЖНО быть удалено, и любые будущие подписчики этой темы не получат сохраненное сообщение[MQTT-3.3.1-6]. Сохраненное сообщение с Payload, содержащим 0 байт, НЕ ДОЛЖНО быть сохранено как retained message на Сервере[MQTT-3.3.1-7].

Если флаг RETAIN 0 в пакете PUBLISH, отправленном Клиентом Серверу, то Сервер НЕ ДОЛЖЕН сохранять сообщение как retained message, и НЕ ДОЛЖЕН удалять или заменять любое существующее retained message[MQTT-3.3.1-8].

Если Сервер подключил Retain Available со значением 0 в ответ CONNACK для Клиента, и Сервер получил пакет PUBLISH с флагом RETAIN, установленным в 1, то Сервер использует DISCONNECT с Reason Code 0x9A (Retain not supported), как описано в секции 4.13.

Когда делается новая не общая подписка (Non‑shared Subscription), последнее retained message, если оно имеется, на каждом совпавшем имени темы отправляется Клиенту, как указано опцией обработки сохраненной подписки (Retain Handling Subscription Option). Эти сообщения отправляются с флагом RETAIN, установленным в 1. Какие retained-сообщения отправляются, определяется опцией Retain Handling Subscription. Во время подписки (Subscription):

· Если Retain Handling установлено в 0, то Сервер ДОЛЖЕН отправить Клиенту retained-сообщения, соответствующие Topic Filter подписки[MQTT-3.3.1-9].
· Если Retain Handling установлено в 1, то если подписка еще не существует, то Сервер ДОЛЖЕН Клиенту все retained-сообщения, соответствующие Topic Filter подписки, и если подписка существует, то Сервер НЕ ДОЛЖЕН отправлять retained messages[MQTT-3.3.1-10].
· Если Retain Handling установлено в 2, то Сервер НЕ ДОЛЖЕН отправлять retained messages[MQTT-3.3.1-11].

Обратитесь к секции 3.8.3.1 для определения опций подписки (Subscription Options).

Если Сервер получил пакет PUBLISH с флагом RETAIN, установленным в 1, и QoS0, то он МОЖЕТ сохранить новое сообщение QoS0 в качестве нового retained message для этой темы, однако МОЖЕТ выбрать отбросить сообщение в любой момент. If this happens there will be no retained message for that topic.

Если хранение текущего retained message для темы (Topic) истекло, оно отбрасывается, и для этой темы не будет retained message.

Установка фдага RETAIN flag в Application Message, перенаправляемого севером из установленного соединения, управляется опцией подписки Retain As Published. Обратитесь к секции 3.8.3.1 для определения опций подписки (Subscription Options).

· Если значение опции подписки Retain As Published установлено 0, то Сервер ДОЛЖЕН установить флаг RETAIN в 0, когда перенаправляет Application Message независимо от того, как был установлен флаг RETAIN в принятом пакете PUBLISH[MQTT-3.3.1-12].
· Если значение опции Retain As Published установлено в 1, то Сервер ДОЛЖЕН установить флаг RETAIN равным флагу RETAIN в принятом пакете PUBLISH[MQTT-3.3.1-13].

Замечание: retained-сообщения полезны, когда публикаторы посылают сообщения состояния нерегулярно. Новый не состоящий в общей подписке пописчик получит самое свежее состояние.

3.3.1.4. Remaining Length. Это длина Variable Header плюс длина Payload, закодированная как Variable Byte Integer.

3.3.2. PUBLISH Variable Header. Variable Header пакета PUBLISH Packet содержит поля, указанные в следующем порядке: Topic Name (имя темы), Packet Identifier (идентификатор пакета) и Properties (свойства). Правила кодирования свойств описаны в секции 2.2.2.

3.3.2.1. Topic Name. Имя темы, идентифицирует информационный канал, куда публикуются данные Payload.

Topic Name ДОЛЖЕН быть представлен как первое поле в Variable Header пакета PUBLISH. Это ДОЛЖНА быть строка (UTF-8 Encoded String), как определено в секции 1.5.4[MQTT-3.3.2-1].

Topic Name в пакете PUBLISH packet НЕ ДОЛЖНО содержать wildcard-символы[MQTT-3.3.2-2].

Topic Name в пакете PUBLISH, посылаемом Сервером Клиенту-подписчику, ДОЛЖЕН соответствовать фильтру темы подписки (Subscription Topic Filter), определено в описании процесса совпадения фильтру секции 4.7[MQTT-3.3.2-3]. Однако поскольку Серверу разрешено оторазить Topic Name на другое имя, имя темы может быть не такое же, как Topic Name в оригинальном пакете PUBLISH.

Для уменьшения размера пакета PUBLISH отправитель может использовать псевдоним темы (Topic Alias). Topic Alias описан в секции 3.3.2.3.4. Если Topic Name нулевой длины, и нет для него Topic Alias, то это Protocol Error.

3.3.2.2. Packet Identifier. Поле идентификатора пакета присутствует только в пакетах PUBLISH, где уровень QoS равен 1 или 2. Секция 2.2.1 предоставляет больше информации об идентификаторах пакета.

3.3.2.3. PUBLISH Properties.

3.3.2.3.1. Property Length. Длина свойств в Variable Header пакета PUBLISH, закодированная как Variable Byte Integer.

3.3.2.3.2. Payload Format Indicator. 1 (0x01), идентификатор Payload Format Indicator.

За ним идет значение индикатора формата полезной нагрузки (Payload Format Indicator), которое может быть одним из следующих величин:

0 (0x00) байт, показывает что в Payload неопределенное количество байт, что эквивалентно отсутствию отправки Payload Format Indicator.
1 (0x01) байт, показывает что в Payload данные символов (UTF-8 Encoded Character Data). Данные UTF-8 полезной нагрузки ДОЛЖНЫ быть правильно сформированным UTF-8, как это определено спецификацией Unicode в RFC 3629.

Сервер ДОЛЖЕН посылать Payload Format Indicator не измененным всем подписчикам, получающим Application Message[MQTT-3.3.2-4]. Получатель МОЖЕТ проверить, что полезная нагрузка обозначена индикатором формата, и если это так, то не отправлять PUBACK, PUBREC или DISCONNECT с Reason Code 0x99 (Payload format invalid), как описано в секции 4.13. См. секцию 5.4.9 для описания проблем безопасности, связанных с проверкой формата полезной нагрузки.

3.3.2.3.3. Message Expiry Interval. 2 (0x02), идентификатор Message Expiry Interval.

За ним идет 4-байтное целое, представляющее интервал устаревания сообщения (Message Expiry Interval).

Если свойство присутствует, то 4-байтное значение представляет время жизни Application Message в секундах. Если указанный интервал истек, и Серверу не удалось начать доставку сообщения соответствующему подписчику, то Сервер ДОЛЖЕН удалить копию сообщения для этого подписчика[MQTT-3.3.2-5].

Если свойство отсутствует, то Application Message не устаревает.

Пакет PUBLISH, отправленный Клиенту Сервером, ДОЛЖЕН содержать Message Expiry Interval, установленный в принятое значение минус время, которое Application Message ожидало на Сервере[MQTT-3.3.2-6]. См. секцию 4.1 для подробностей и ограничениям сохраненного состояния.

3.3.2.3.4. Topic Alias. 35 (0x23), идентификатор псевдонима темы (Topic Alias).

За ним идет 2-байтное целое, представляющее значение псевдонима темы. Если Topic Alias указано больше одного раза, то это Protocol Error.

Topic Alias это целочисленное значение, используемое для идентификации темы вместо использования для этой же цели имени темы (Topic Name). Это уменьшает размер пакета PUBLISH, и полезно, когда имена тем длинные, и постоянно повторяются во время действия сетевого соединения.

Отправитель решает, использовать ли псевдоним темы, и выбирает для него значение. Он устанавливает взаимосвязь Topic Alias с именем темы (Topic Name), включая в пакет PUBLISH значение Topic Alias и строку Topic Name ненулевой длины. Получатель обрабатывает пакет PUBLISH как обычно, и устанавливает для себя соответствие между Topic Alias и его Topic Name.

Если отображение Topic Alias было установлено получателем, то Сервер может послать пакет PUBLISH, который содержит Topic Alias и Topic Name нулевой длины. Тогда получатель обработает поступивший пакет PUBLISH, как если бы он содержиат Topic Name, соответствующий полученному Topic Alias.

Отправитель может модифицировать взаимосвязь Topic Alias и Topic Name путем отправки другого пакета PUBLISH на том же самом сетевом соединении, с таким же значением Topic Alias и другим Topic Name ненулевой длины.

Отображение псеводонима темы на имя темы существует только в пределах одного сетевого соединения и только в течение времени жизни этого сетевого соединения. Получатель НЕ ДОЛЖЕН не должен переносить любые отображения псевдонимов тем с одного сетевого соединения на другое сетевое соединение[MQTT-3.3.2-7].

Topic Alias 0 не разрешается. Отправитель НЕ ДОЛЖЕН посылать пакет PUBLISH, содержащий Topic Alias, у которого значение 0[MQTT-3.3.2-8].

Клиент НЕ ДОЛЖЕН посылать пакет PUBLISH со значением Topic Alias, превышающим значение Topic Alias Maximum, возвращенное Сервером в пакете CONNACK[MQTT-3.3.2-9]. Клиент ДОЛЖЕН принимать все значения Topic Alias, которые больше 0, и меньшие или равные значению Topic Alias Maximum, которое было отправлено в пакете CONNECT[MQTT-3.3.2-10].

Сервер НЕ ДОЛЖЕН посылать пакет PUBLISH с Topic Alias, который больше значения Topic Alias Maximum, отправленного Клиентом в пакете CONNECT[MQTT-3.3.2-11]. Сервер ДОЛЖЕН принимать все значения Topic Alias, которые больше 0 и меньше или равны значению Topic Alias Maximum, которое было возвращено в пакете CONNACK[MQTT-3.3.2-12].

Отображения Topic Alias, используемые Клиентом и Сервером, не зависят друг от друга. Таким образом, когда Клиент посылает Серверу пакет PUBLISH, содержащий значение Topic Alias 1, и Сервер посылает Клиенту пакет PUBLISH со значением Topic Alias 1, то в общем случае эти псевдонимы ссылаются на различные темы сообщений.

3.3.2.3.5. Response Topic. 8 (0x08), идентификатор Response Topic.

За ним идет строка (UTF-8 Encoded String), которая используется как имя темы (Topic Name) для сообщения ответа (response message). Response Topic ДОЛЖЕН быть UTF-8 Encoded String, как это определено в секции 1.5.4[MQTT-3.3.2-13]. Response Topic НЕ ДОЛЖЕН содержать wildcard-символы[MQTT-3.3.2-14]. Если Response Topic указано больше одного раза, то это Protocol Error. Наличие Response Topic идентифицирует сообщение (Message) как запрос (Request).

См. секцию 4.10 для дополнительной информации по запросу/ответу (Request / Response).

Сервер ДОЛЖЕН посылать Response Topic не измененным всем подписчикам, принимающим Application Message[MQTT-3.3.2-15].

Замечание: получатель Application Message с Response Topic отправляет ответ, используя Response Topic в качестве Topic Name пакета PUBLISH. Если Request Message содержит данные корреляции (Correlation Data), то получатель Request Message может также подключить эти Correlation Data ка свойство в пакет PUBLISH сообщения ответа (Response Message).

3.3.2.3.6. Correlation Data. 9 (0x09), идентификатор данных корреляции.

За ним идут двочные данные (Binary Data). Correlation Data используются отправителем сообщения запроса (Request Message) для идентификации того какой запрос является ответным сообщением при его получении. Если Correlation Data указано больше одного раза, то это Protocol Error. Если Correlation Data отсутствуют, то запрашивающий не требует никаких данных корреляции.

Сервер ДОЛЖЕН посылать Correlation Data не измененными всем подписчикам, получающим Application Message[MQTT-3.3.2-16]. Значение Correlation Data имеет смысл только для отправителя сообщения запроса (Request Message) и получателя сообщения ответа (Response Message).

Замечания:

1. Получатель Application Message, которое содежит и Response Topic, и Correlation Data, посылает ответ с использованием Response Topic в качестве имени темы (Topic Name) пакета PUBLISH. Клиент должен также посылать Correlation Data не измененными как часть пакета PUBLISH ответов.
2. Если Correlation Data содержат информацию, которая может привести к сбоям приложения в случае, когда Клиент их модифицирует, отвечая на запрос, то эти данные корреляции должны быть зашифрованы и/или защищены хэшем, чтобы можно было обнаружить изменение данных корреляции.

См. секцию 4.10 для дополнительной информации по запросу/ответу (Request / Response).

3.3.2.3.7. User Property. 38 (0x26), идентификатор свойства пользователя (User Property).

За ним идет пара строк (UTF-8 String Pair). Свойство пользователя может появляться несколько раз, чтобы несколько раз передать пары имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

Сервер ДОЛЖЕН посылать все свойства пользователя не измененными в пакете PUBLISH, когда Сервер перенаправляет Application Message Клиенту[MQTT-3.3.2-17]. Сервер ДОЛЖЕН сохранять порядок следования свойств пользователя, когда осуществляет перенаправление Application Message[MQTT-3.3.2-18].

Замечание: это свойство предназначено для предоставления способа передачи тегов name-value, смысл и интерпретация которых относятся только к программам приложения, которые передают и принимают эти теги.

3.3.2.3.8. Subscription Identifier. 11 (0x0B), идентификатор идентификатора подписки (Subscription Identifier).

За ним идет Variable Byte Integer, представляющее идентификатор подписки.

Subscription Identifier может иметь значение в диапазоне 1 .. 268435455. Если Subscription Identifier имеет значение 0, то это Protocol Error. Будут подключены несколько идентификаторов подписки, если публикация это результат больше чем одной подписки, в этом случае их порядок не имеет значение.

3.3.2.3.9. Content Type. 3 (0x03), идентификатор типа содержимого (Content Type).

За ним идет строка (UTF-8 Encoded String), описывающая содержимое Application Message. Тип содежимого ДОЛЖЕН быть UTF-8 Encoded String, как это определено в секции 1.5.4[MQTT-3.3.2-19].

Если Content Type указано больше одного раза, то это Protocol Error. Значение Content Type определяется отправляющим и принимающим приложением.

Сервер ДОЛЖЕН посылать Content Type не измененным всем подписчикам, получющим Application Message[MQTT-3.3.2-20].

Замечания:

1. UTF-8 Encoded String может использовать строку MIME content type для описания содержимого Application Message. Однако поскольку отправляющее и принимающее приложения отвечают за определение и интерпретацию этой строки, MQTT не выполняет проверку строки за исключением её соответствия формату UTF-8 Encoded String.
2. Рис. 3-9 показывает пример пакета PUBLISH с Topic Name, установленным в "a/b", Packet Identifier, установленным в 10, без свойств.

  Описание 7 6 5 4 3 2 1 0
Имя темы (Topic Name)
Байт 1 MSB длины (0) 0 0 0 0 0 0 0 0
Байт 2 LSB длины (3) 0 0 0 0 0 0 1 1
Байт 3 'a' (0x61) 0 1 1 0 0 0 0 1
Байт 4 '/' (0x2F) 0 0 1 0 1 1 1 1
Байт 5 'b' (0x62) 0 1 1 0 0 0 1 0
Идентификатор пакета
Байт 6 MSB Packet Identifier (0) 0 0 0 0 0 0 0 0
Байт 7 LSB Packet Identifier (10) 0 0 0 0 1 0 1 0
Длина свойств
Байт 8 Нет свойств 0 0 0 0 0 0 0 0

Рис. 3‑9. Пример Variable Header пакета PUBLISH.

3.3.3. PUBLISH Payload. Полезная нагрузка (Payload) содержит публикуемое Application Message. Содержимое и формат полезной нагрузки специфичны для приложения. Длина полезной нагрузки может быть вычислена путем вычитания длины Variable Header из поля Remaining Length в Fixed Header. Для пакета PUBLISH допустимо содержать полезную нагрузку нулевой длины.

3.3.4. PUBLISH Actions. Получатель пакета PUBLISH ДОЛЖЕН отвечать пакетом, как это определено QoS пакета PUBLISH[MQTT-3.3.4-1].

Таблица 3‑3. Ожидаемый ответ на пакет PUBLISH.

Уровень QoS Ожидаемый ответ
QoS0 Нет
QoS1 Пакет PUBACK
QoS2 Пакет PUBREC

Клиент использует пакет PUBLISH для отправки Application Message на Сервер, чтобы распространить сообщение Клиентам с соответствующей подпиской.

Сервер использует пакет PUBLISH для отправки Application Message каждому Клиенту, у которого есть соответствующая подписка. Пакет PUBLISH включает идентификатор подписки (Subscription Identifier), который был передан в пакете SUBSCRIBE, если таковой был.

Когда Клиенты делают подписки с фильтрами темы (Topic Filter), которые содержат символы wildcard, существует возможность перекрытия подписок Клиента, когда публикуемое сообщение соответствует нескольким фильтрам. В этом случае Сервер ДОЛЖЕН доставить сообщение Клиенту в соответствии с максимальным QoS всех совпавших подписок[MQTT-3.3.4-2]. Дополнительно Сервер МОЖЕТ доставить дополнительные копии сообщения, по одному для каждой дополнительной совпавшей подписки, с соблюдением QoS для каждого случая.

Если Клиент получает не запрашиваемое Application Message (которое не является результатом подписки), у которого QoS превышает Maximum QoS, то Клиент использует пакет DISCONNECT с Reason Code 0x9B (QoS not supported), как описано в секции 4.13 по обработке ошибок.

Если Сервер указал идентификатор подписки Subscription Identifier для любой из перекрывающих друг друга подписок, то Сервер ДОЛЖЕН посылать посылать эти идентификаторы подписки в сообщении, которое публикуется как результат подписок[MQTT-3.3.4-3]. Если Сервер посылает одну копию сообщения, то он ДОЛЖЕН подключить в пакет PUBLISH идентификаторы подписки для всех подходящих подписок, у которых есть идентификаторы подписки, причем их порядок следования не имеет значения[MQTT-3.3.4-4]. Если Сервер посылает несколько пакетов PUBLISH, которые он ДОЛЖЕН отправить, в каждом из них идентификатор подписки соответствующей подписки, если у него есть Subscription Identifier[MQTT-3.3.4-5].

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

Если пакет PUBLISH содержит любые идентификаторы подписки, отличающиеся от полученных в пакете SUBSCRIBE, то это Protocol Error. Пакет PUBLISH, отправленный Клиентом Серверу, НЕ ДОЛЖЕН содержать идентификатор подписки[MQTT-3.3.4-6].

Если подписка была общей, то в пакете PUBLISH возвращаются только идентификаторы подписки, которые присутствовали в пакете SUBSCRIBE от Клиента, принимающего сообщение.

Действие получателя, когда он примет пакет PUBLISH, зависит от уровня QoS, как это описано в секции 4.3.

Если пакет PUBLISH содержит Topic Alias, то получатель обрабатывает это следующим образом:

1) Значение 0 Topic Alias, или большее чем Maximum Topic Alias, соответствует Protocol Error, тогда получатель использует DISCONNECT с Reason Code 0x94 (Topic Alias invalid), как описано в секции 4.13.

2) Если получатель уже установил соответствие для Topic Alias, то:

    a) Если у пакета Topic Name нулевой длины, то получатель обрабатывает это, используя Topic Name, соответствующий Topic Alias.

    b) Если пакет содержит Topic Name ненулевой длины, то получатель обрабатывает пакет, используя это Topic Name, и обновляет отображение этого имени из пришедшего пакета на Topic Alias.

3) Если у получателя нет еще отображения для этого Topic Alias, то:

    a) Если у пакета есть поле Topic Name нулевой длины, то это Protocol Error, и получатель использует DISCONNECT с Reason Code 0x82 (Protocol Error), как описано в секции 4.13.

    b) Если пакет содержит Topic Name ненулевой длины, то получатель обрабатывает пакет, используя это Topic Name, и устанавливает его отображение на Topic Alias, поступивший в полученном пакете.

Замечание: если Сервер публикует Application Message для Клиентов на другом уровне протокола (таком как MQTT V3.1.1) который не поддерживает свойства и ли другие возможности, предоставляемые этой спецификацией MQTT, то некоторая информация в Application Message может быть потеряна, и приложения, которые зависят от этой информации, могут работать некорректно.

Клиент НЕ ДОЛЖЕН отправлять от Сервера более пакетов Receive Maximum QoS 1 и QoS 2 PUBLISH, для которых он не получил PUBACK, PUBCOMP или PUBREC с кодом причины 128 или более[MQTT-3.3.4-7]. Если он принял пакеты PUBLISH с более чем Receive Maximum QoS1 и QoS2 PUBLISH, где он не отправил PUBACK или PUBCOMP в ответ, то Сервер использует пакет DISCONNECT с Reason Code 0x93 (Receive Maximum exceeded) как описано в секции 4.13 по обработке ошибок. Обратитесь к секции 4.9 для дополнительной информации по управлению потоком (flow control).

Клиент НЕ ДОЛЖЕН задерживать отправку любых пакетов, отличающихся от PUBLISH, из-за отправки пакетов Receive Maximum PUBLISH без приема подтверждений для них[MQTT-3.3.4-8]. Значение Receive Maximum применимо только для текущего сетевого соединения.

Замечания:

- Клиент может выбрать отправку на Сервер меньше чем Receive Maximum сообщений без получения подтверждения, даже если имеется больше этого количества сообщений для отправки.
- Клиент может выбрать приостановку отправки пакетов QoS0 PUBLISH, когда он приостановил отправку пакетов QoS1 и QoS2 PUBLISH.
- Если Клиент послал QoS1 или QoS2 пакеты PUBLISH до получения пакета CONNACK, то есть риск отключения из-за того, что превышено Receive Maximum публикаций.

Сервер НЕ ДОЛЖЕН посылать больше чем Receive Maximum QoS1 и QoS2 пакетов PUBLISH, для которых от Клиента не получены PUBACK, PUBCOMP или PUBREC с Reason Code 128 или больше[MQTT-3.3.4-9]. Если Клиент получил больше Receive Maximum QoS1 и QoS 2 пактов PUBLISH, на которые в ответ не были отправлены PUBACK или PUBCOMP, то Клиент использует DISCONNECT с Reason Code 0x93 (Receive Maximum exceeded), как описано в секции 4.13 по обработке ошибок. Обратитесь к секции 4.9 для дополнительной информации по управлению потоком (flow control).

Сервер НЕ ДОЛЖЕН задерживать отправку любых пакетов, отличающихся от пакетов PUBLISH из-за отправки пакетов Receive Maximum PUBLISH без получения для них подтверждений[MQTT-3.3.4-10].

Замечания:

- Сервер может выбрать отправить меньше чем Receive Maximum сообщений Клиенту без получения подтверждения, даже если имеет большее, чем это число сообщений, доступных для отправки.
- Сервер может выбрать приостановку отправки пакетов QoS0 PUBLISH, когда он приостановил отправку пакетов QoS1 и QoS2 PUBLISH.

3.4. PUBACK – Publish acknowledgement. Пакет PUBACK это подтверждение пакета PUBLISH с QoS1.

3.4.1. PUBACK Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (4) Зарезервировано
  0 1 0 0 0 0 0 0
Байт 2 Remaining Length

Рис. 3‑10. Fixed Header.

Поле Remaining Length. Это длина Variable Header, закодированная как Variable Byte Integer.

3.4.2. PUBACK Variable Header. Variable Header пакета PUBACK Packet содержит поля, идущие в следующем порядке: Packet Identifier из пакета PUBLISH, который подтверждается, PUBACK Reason Code, Property Length (длина свойств) и Properties (свойства). Правила для кодирования свойств описаны в секции 2.2.2.

Бит 7 6 5 4 3 2 1 0
Байт 1 MSB Packet Identifier
Байт 2 LSB Packet Identifier
Байт 3 PUBACK Reason Code
Байт 4 Property Length

Рис. 3‑11. Variable Header пакета PUBACK.

3.4.2.1. PUBACK Reason Code. Байт 3 в Variable Header это PUBACK Reason Code. Если оставшаяся длина (Remaining Length) равна 2, то здесь нет Reason Code, и используется значение 0x00 (Success).

Таблица 3‑4. PUBACK Reason Codes.

Dec Hex Имя Reason Code
Описание
0 0x00 Успешное завершение Сообщение принято. Продолжается публикация сообщения QoS 1.
16 0x10 Нет совпавших идентификаторов Сообщение принято, но нет подписчиков. Это сообщение отправляется только Сервером. Если Сервер знает, что нет соответствующих абонентов, он МОЖЕТ использовать этот код причины вместо 0x00 (Success).
128 0x80 Неопределенная ошибка Получатель не принимает публикацию, но либо не хочет раскрывать причину, либо она не соответствует одному из других значений.
131 0x83 Ошибка, специфичная для реализации Параметр PUBLISH корректен, но получатель не желает его принимать.
135 0x87 Не авторизовано Пакет PUBLISH не авторизован.
144 0x90 Недопустимое Topic Name Topic Name сформировано корректно, но оно не может быть принято этим Клиентом или Сервером.
145 0x91 Packet identifier уже используется Идентификатор пакета уже используется. Это может указывать на несоответствие в состоянии сеанса между Клиентом и Сервером.
151 0x97 Превышена квота Превышение реализации, или превышен установленный административно предел.
153 0x99 Недопустимый формат полезной нагрузки Формат Payload не соответствует указанному Payload Format Indicator.

Клиент или Сервер, посылающий пакет PUBACK, ДОЛЖЕН использовать один из кодов PUBACK Reason Codes[MQTT-3.4.2-1]. Reason Code и Property Length могут быть опущены, если Reason Code 0x00 (Success), и здесь нет свойств Properties. В этом случае у Remaining Length пакета PUBACK значение 2.

3.4.2.2. PUBACK Properties.

3.4.2.2.1. Property Length. Это длина свойств в Variable Header пакета PUBACK, закодированная как Variable Byte Integer. Если Remaining Length меньше 4, то здесь нет Property Length, и используется значение 0.

3.4.2.2.2. Reason String. 31 (0x1F), идентификатор Reason String.

За ним идет строка (UTF-8 Encoded String), представляющая причину, связанную с этим ответом. Reason String это удобочитаемая строка, разработанная для целей диагностики, и она не предназначена для парсинга получателем.

Отправитель использует это значение для предоставления дополнительной информации для получателя. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка увеличит размер пакета PUBACK сверх Maximum Packet Size, указанного получателем[MQTT-3.4.2-2]. Если Reason String указано больше одного раза, то это Protocol Error.

3.4.2.2.3. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной диагностики или передачи другой информации. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка увеличит размер пакета PUBACK сверх Maximum Packet Size, указанного получателем[MQTT-3.4.2-3]. User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

3.4.3. PUBACK Payload. У пакета PUBACK нет полезной нагрузки.

3.4.4. PUBACK Actions. Это описано в секции 4.3.2.

3.5. PUBREC – принят Publish (доставка QoS2, часть 1).

Пакет PUBREC это ответ на пакет PUBLISH, у которого установлено качество доставки QoS2. Это второй пакет протокола обмена QoS2.

3.5.1. PUBREC Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (5) Зарезервировано
  0 1 0 1 0 0 0 0
Байт 2 Remaining Length

Рис. 3‑12. Fixed Header пакета PUBREC.

Поле Remaining Length. Это длина Variable Header, закодированная как Variable Byte Integer.

3.5.2. PUBREC Variable Header. Variable Header пакета PUBREC состоит из полей, идущих в следующем порядке: Packet Identifier из подтверждаемого пакета PUBLISH, PUBREC Reason Code и Properties. Правила для кодирования свойств описаны в секции 2.2.2.

Бит 7 6 5 4 3 2 1 0
Байт 1 MSB Packet Identifier
Байт 2 LSB Packet Identifier
Байт 3 PUBREC Reason Code
Байт 4 Property Length

Рис. 3‑13. Variable Header пакета PUBREC.

3.5.2.1. PUBREC Reason Code. Байт 3 в Variable Header это Reason Code пакета PUBREC. Если Remaining Length равно 2, то у Publish Reason Code значение 0x00 (Success).

Таблица 3‑5. PUBREC Reason Codes.

Dec Hex Имя Reason Code
Описание
0 0x00 Успешное завершение Сообщение принято. Продолжается публикация сообщения QoS 2.
16 0x10 Нет совпавших идентификаторов Сообщение принято, но нет подписчиков. Это сообщение отправляется только Сервером. Если Сервер знает, что нет соответствующих абонентов, он МОЖЕТ использовать этот код причины вместо 0x00 (Success).
128 0x80 Неопределенная ошибка Получатель не принимает публикацию, но либо не хочет раскрывать причину, либо она не соответствует одному из других значений.
131 0x83 Ошибка, специфичная для реализации Параметр PUBLISH корректен, но получатель не желает его принимать.
135 0x87 Не авторизовано Пакет PUBLISH не авторизован.
144 0x90 Недопустимое Topic Name Topic Name сформировано корректно, но оно не может быть принято этим Клиентом или Сервером.
145 0x91 Packet identifier уже используется Идентификатор пакета уже используется. Это может указывать на несоответствие в состоянии сеанса между Клиентом и Сервером.
151 0x97 Превышена квота Превышение реализации, или превышен установленный административно предел.
153 0x99 Недопустимый формат полезной нагрузки Формат Payload не соответствует указанному Payload Format Indicator.

Клиент или Сервер, посылающий пакет PUBREC, ДОЛЖЕН использовать одно из значений PUBREC Reason Code[MQTT-3.5.2-1]. Reason Code и Property Length могут быть опущены, если Reason Code 0x00 (Success), и здесь нет свойств Properties. В этом случае у пакета PUBREC значение Remaining Length равно 2.

3.5.2.2. PUBREC Properties.

3.5.2.2.1. Property Length. Длина свойств в Variable Header пакета PUBREC, закодированная как Variable Byte Integer. Если Remaining Length меньше 4, то здесь нет Property Length, и используется значение 0.

3.5.2.2.2. Reason String. 31 (0x1F), идентификатор Reason String.

Далее идет строка (UTF-8 Encoded String), представляющая причину, связанную с этим ответом. Reason String это удобочитаемая строка, разработанная для диагностики, она НЕОБЯЗАТЕЛЬНО ДОЛЖНА быть обработана получателем.

Отправитель использует это значение для предоставления дополнительной информации получателю. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета PUBREC свыше Maximum Packet Size, указанного получателем[MQTT-3.5.2-2]. Если Reason String указано больше одного раза, то это Protocol Error.

3.5.2.2.3. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной диагностики или передачи другой информации. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета PUBREC свыше Maximum Packet Size, указанного получателем[MQTT-3.5.2-3]. User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

3.5.3. PUBREC Payload. У пакета PUBREC нет полезной нагрузки.

3.5.4. PUBREC Actions. Это описано в секции 4.3.3.

3.6. PUBREL – Publish release (доставка QoS2, часть 2).

Пакет PUBREL это ответ на пакет PUBREC. Это третий пакет протокола обмена QoS2.

3.6.1. PUBREL Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (6) Зарезервировано
  0 1 1 0 0 0 1 0
Байт 2 Remaining Length

Рис. 3‑14. Fixed Header пакета PUBREL.

Биты 3, 2, 1 и 0 в Fixed Header пакета PUBREL зарезервированы, и ДОЛЖНЫ быть установлены соответственно в значения 0, 0, 1 и 0. Отправитель ДОЛЖЕН обрабатывать любое другое значение этих бит как ошибку, и закрывать сетевое соединение[MQTT-3.6.1-1].

Поле Remaining Length. Это длина Variable Header, закодированная как Variable Byte Integer.

3.6.2. PUBREL Variable Header. Variable Header пакета PUBREL содержит поля в следующем порядке: Packet Identifier из подтверждаемого пакета PUBREC, PUBREL Reason Code и Properties. Правила для кодирования свойств описаны в секции 2.2.2.

Бит 7 6 5 4 3 2 1 0
Байт 1 MSB Packet Identifier
Байт 2 LSB Packet Identifier
Байт 3 PUBREL Reason Code
Байт 4 Property Length

Рис. 3‑15. Variable Header пакета PUBREL.

3.6.2.1. PUBREL Reason Code. Байт 3 в Variable Header это PUBREL Reason Code. Если Remaining Length равно 2, то используется значение 0x00 (Success).

Таблица 3‑6. PUBREL Reason Codes.

Dec Hex Имя Reason Code
Описание
0 0x00 Успешное завершение Сообщение освобождено.
146 0x92 Packet identifier не найден Идентификатор пакета неизвестен. Это не ошибка во время восстановления, но в другое время указывает на несоответствие между состоянием сеанса (Session State) на Клиенте и Сервере.

Клиент или Сервер, посылающий пакет PUBREL, ДОЛЖЕН использовать одно из значений PUBREL Reason Code[MQTT-3.6.2-1]. Reason Code и Property Length могут быть опущены, если Reason Code 0x00 (Success), и здесь нет свойств Properties. В этом случае Remaining Length пакета PUBREL равна 2.

3.6.2.2. PUBREL Properties.

3.6.2.2.1. Property Length. Длина свойств Variable Header пакета PUBREL, закодированная как Variable Byte Integer. Если Remaining Length меньше 4, то здесь нет Property Length, и используется значение 0.

3.6.2.2.2. Reason String. 31 (0x1F), идентификатор Reason String.

Далее идет строка (UTF-8 Encoded String), представляющая причину, связанную с этим ответом. Reason String это удобочитаемая строка, разработанная для диагностики, она НЕОБЯЗАТЕЛЬНО ДОЛЖНА быть обработана получателем.

Отправитель использует это значение для предоставления дополнительной информации получателю. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета PUBREL свыше Maximum Packet Size, указанного получателем[MQTT-3.6.2-2]. Если Reason String указано больше одного раза, то это Protocol Error.

3.6.2.2.3. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной диагностики или передачи другой информации пакета PUBREL. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета PUBREL свыше Maximum Packet Size, указанного получателем[MQTT-3.6.2-3]. User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

3.6.3. PUBREL Payload. У пакета PUBREL нет полезной нагрузки.

3.6.4. PUBREL Actions. Это описано в секции 4.3.3.

3.7. PUBCOMP – Publish complete (доставка QoS2, часть 3).

Пакет PUBCOMP это ответ на пакет PUBREL. Это четвертый, последний пакет протокола обмена QoS2.

3.7.1. PUBCOMP Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (7) Зарезервировано
  0 1 1 1 0 0 0 0
Байт 2 Remaining Length

Рис. 3‑16. Fixed Header пакета PUBCOMP.

Remaining Length. Это длина Variable Header, закодированная как Variable Byte Integer.

3.7.2. PUBCOMP Variable Header. Variable Header пакета PUBCOMP содержит поля в следующем порядке: Packet Identifier из подтверждаемого пакета PUBREL, PUBCOMP Reason Code и Properties. Правила для кодирования свойств описаны в секции 2.2.2.

Бит 7 6 5 4 3 2 1 0
Байт 1 MSB Packet Identifier
Байт 2 LSB Packet Identifier
Байт 3 PUBCOMP Reason Code
Байт 4 Property Length

Рис. 3‑17. Variable Header пакета PUBCOMP.

3.7.2.1. PUBCOMP Reason Code. Байт 3 в Variable Header это PUBCOMP Reason Code. Если Remaining Length равно 2, то используется значение 0x00 (Success).

Таблица 3‑7. PUBCOMP Reason Codes.

Dec Hex Имя Reason Code
Описание
0 0x00 Успешное завершение Packet identifier освобожден. Публикация сообщения QoS2 завершено.
146 0x92 Packet identifier не найден Идентификатор пакета неизвестен. Это не ошибка во время восстановления, но в другое время указывает на несоответствие между состоянием сеанса (Session State) на Клиенте и Сервере.

Клиент или Сервер, отправляющий пакет PUBCOMP, ДОЛЖЕН использовать одно из значений PUBCOMP Reason Code[MQTT-3.7.2-1]. Reason Code и Property Length могут быть опущены, если Reason Code 0x00 (Success), и здесь нет свойств Properties. В этом случае Remaining Length пакета PUBCOMP равна 2.

3.7.2.2. PUBCOMP Properties.

3.7.2.2.1. Property Length. Длина свойств Variable Header пакета PUBCOMP, закодированная как Variable Byte Integer. Если Remaining Length меньше 4, то здесь нет Property Length, и используется значение 0.

3.7.2.2.2. Reason String. 31 (0x1F), идентификатор Reason String.

Далее идет строка (UTF-8 Encoded String), представляющая причину, связанную с этим ответом. Reason String это удобочитаемая строка, разработанная для диагностики, и она НЕОБЯЗАТЕЛЬНО ДОЛЖНА быть обработана получателем.

Отправитель использует это значение для предоставления дополнительной информации получателю. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета PUBCOMP свыше Maximum Packet Size, указанного получателем[MQTT-3.7.2-2]. Если Reason String указано больше одного раза, то это Protocol Error.

3.7.2.2.3. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной диагностики или передачи другой информации. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета PUBCOMP свыше Maximum Packet Size, указанного получателем[MQTT-3.7.2-3]. User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

3.7.3. PUBCOMP Payload. У пакета PUBCOMP нет полезной нагрузки.

3.7.4. PUBCOMP Actions. Это описано в секции 4.3.3.

3.8. SUBSCRIBE - запрос на подписку. Пакет SUBSCRIBE отправляет Клиент Серверу для создания одной или нескольких подписок (Subscription). Каждая подписка регистрирует интерес Клиента к одной или большему количеству тем сообщений (Topic). Сервер посылает пакеты PUBLISH Клиенту для перенаправления Application Messages, которые были опубликованы в темы, соответствующие этим подпискам. Пакет SUBSCRIBE также указывает (для каждой подписки) максимальный уровень QoS, с которым Сервер может отправить Application Messages Клиенту.

3.8.1. SUBSCRIBE Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (8) Зарезервировано
  1 0 0 0 0 0 1 0
Байт 2 Remaining Length

Рис. 3‑18. Fixed Header пакета SUBSCRIBE.

Биты 3, 2, 1 и 0 в Fixed Header пакета SUBSCRIBE зарезервированы, и ДОЛЖНЫ быть установлены в значения 0, 0, 1 и 0 соответственно. Сервер ДОЛЖЕН обрабатывать любое другое значение этих бит как ошибку, и закрывать сетевое соединение[MQTT-3.8.1-1].

Remaining Length. Это длина Variable Header плюс длина Payload (полезной нагрузки), закодированная как Variable Byte Integer.

3.8.2. SUBSCRIBE Variable Header. Variable Header пакета SUBSCRIBE содержит поля в следующем порядке: Packet Identifier и Properties. Секция 2.2.1 предоставляет больше информации об идентификаторах пакета. Правила для кодирования свойств описаны в секции 2.2.2.

На рисунке 3-19 показан пример переменного заголовка пакета SUBSCRIBE с идентификатором пакета 10 и без свойств.

  Описание 7 6 5 4 3 2 1 0
Идентификатор пакета (Packet identifier)
Байт 1 MSB идентификатора пакета (0) 0 0 0 0 0 0 0 0
Байт 2 LSB идентификатора пакета (10) 0 0 0 0 1 0 1 0
Байт 3 Property Length (0) 0 0 0 0 0 0 0 0

Рис. 3‑19. Пример Variable Header пакета SUBSCRIBE.

3.8.2.1. SUBSCRIBE Properties.

3.8.2.1.1. Property Length. Длина свойств в Variable Header пакета SUBSCRIBE, закодированная как Variable Byte Integer.

3.8.2.1.2. Subscription Identifier. 11 (0x0B), идентификатор Subscription Identifier.

За ним идет Variable Byte Integer, представляющий идентификатор подписки (Subscription Identifier). Идентификатор подписки может иметь значение в диапазоне от 1 до 268435455. Если у Subscription Identifier значение 0, то это Protocol Error. Если Subscription Identifier указано больше одного раза, то это Protocol Error.

Идентификатор Subscription Identifier связывается с любой подпиской (или эта связь модифицируется) как результат получения пакета SUBSCRIBE. Если здесь имеется Subscription Identifier, то он сохраняется вместе с подпиской. Если это свойство не указано, то отсутствие Subscription Identifier сохраняется вместе с подпиской.

См. секцию 3.8.3.1 для дополнительной информации по обработке идентификаторов подписки.

3.8.2.1.3. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

Замечание: User Properties пакета SUBSCRIBE может использоваться для отправки Клиентом Серверу связанных с подпиской свойств. Смысл и значение этих свойств не определяется этой спецификацией (т. е. может использоваться приложением отправителя и получателя).

3.8.3. SUBSCRIBE Payload. Полезная нагрузка (Payload) пакета SUBSCRIBE содержит список фильтров тем (Topic Filter), показывающий темы сообщений приложения (Topic), на получение которых Клиент хочет подписаться. Список фильтров тем ДОЛЖЕН строкой UTF-8 Encoded String[MQTT-3.8.3-1]. За каждым Topic Filter идет байт опций подписки (Subscription Options).

Полезная нагрузка пакета подписки ДОЛЖЕНА содержать как минимум одну пару Topic Filter и Subscription Options[MQTT-3.8.3-2]. Пакет SUBSCRIBE без полезной нагрузки это Protocol Error. См. секцию 4.13 для информации по обработке ошибок.

3.8.3.1. Subscription Options. Биты 0 и 1 опций подписки (Subscription Options) представляют поле Maximum QoS. Оно дает максимальный уровень качества доставки (maximum QoS), с которым Сервер может отправить Application Messages Клиенту. Если поле Maximum QoS имеет значение 3, то это Protocol Error.

Бит 2 опций подписки представляет опцию No Local. Если её значение 1, то Application Messages НЕ ДОЛЖНО быть перенаправлено на соединение с ClientID, равное ClientID соединения публикации[MQTT-3.8.3-3]. Если бит No Local установлен в 1 на общей подписке (Shared Subscription), то это Protocol Error[MQTT-3.8.3-4].

Бит 3 опций подписки представляет опцию Retain As Published (сохранять как опубликовано). Если 1, то Application Messages перенаправляется с использованием этой подписки, и с сохранением флага RETAIN, с которым сообщение было опубликовано. Если 0, то Application Messages перенаправляется с использованием этой подписки, и флаг RETAIN устанавливается в 0. Сохраняемые сообщения (Retained Messages) отправляются, когда установлена подписка с флагом RETAIN, установленным в 1.

Биты 4 и 5 опций подписки представляют опцию Retain Handling. Эта опция задает, отправляются ли сохраненные сообщения, когда установлена подписка. Это не влияет на отправку сохраненных сообщений (Retained Messages) в любой момент после подписки. Если ни одно из сохраненных сообщений не соответствует Topic Filter, то все эти значения действуют одинаково. Вот эти значенияThe values are:

0 = отправлять retained messages в момент подписки.
1 = отправлять retained messages при подписке, только если подписка в настоящий момент не существует.
2 = не отправлять retained messages во время подписки.

Если отправляемое Retain Handling имеет значение 3, то это Protocol Error.

Биты 6 и 7 опций подписки зарезервированы для использования в будущем. Сервер ДОЛЖЕН обработать пакет SUBSCRIBE как ошибочный, если любой из зарезервированных бит в Payload не равен 0[MQTT-3.8.3-5].

Замечания:

1. Опции подписки No Local и Retain As Published могут использоваться для реализации моста, где Клиент отправляет сообщение на другой Сервер.
2. Не отправлять retained messages для существующей подписки полезно, когда выполнен реконнект, и Клиенте уверен, были ли завершены подписки на предыдущем соединении для сессии.
3. Не отправлять сохраненные retained messages из-за новой подписки полезно, когда Клиенты хотят получать оповещения изменений, и им не нужно знать начальное состояние.
4. Для Сервера, который показывает отсутствие поддержки retained messages, все допустимые значения Retain As Published и Retain Handling дают одинаковый результат, в котором не будет осуществляться отправка никаких retained messages при подписке, и для установки флага RETAIN в 0 для всех сообщений.

Описание 7 6 5 4     3         2         1         0    
Фильтр темы (Topic Filter)                
Байт 1 MSB длины
Байт 2 LSB длины
Байт 3 Фильтр темы
  Зарезервировано Retain Handling RAP NL QoS
Байт N+1 0 0 X X X X X X

Рис. 3‑20. Формат полезной нагрузки пакета SUBSCRIBE.

RAP означает Retain as Published. NL означает No Local.

На рис. 3.21 показан пример полезной нагрузки пакета SUBSCRIBE с двумя фильтрами тем (Topic Filters). Первый "a/b" с QoS1, и второй "c/d" с QoS2.

  Описание 7 6 5 4 3 2 1 0
Фильтр темы (Topic Filter)
Байт 1 MSB длины (0) 0 0 0 0 0 0 0 0
Байт 2 LSB длины (3) 0 0 0 0 0 0 1 1
Байт 3 'a' (0x61) 0 1 1 0 0 0 0 1
Байт 4 '/' (0x2F) 0 0 1 0 1 1 1 1
Байт 5 'b' (0x62) 0 1 1 0 0 0 1 0
Опции подписки (Subscription Options)
Байт 6 Опции подписки (1) 0 0 0 0 0 0 0 1
Фильтр темы
Байт 7 MSB длины (0) 0 0 0 0 0 0 0 0
Байт 8 LSB длины (3) 0 0 0 0 0 0 1 1
Байт 9 'c' (0x63) 0 1 1 0 0 0 1 1
Байт 10 '/' (0x2F) 0 0 1 0 1 1 1 1
Байт 11 'd' (0x64) 0 1 1 0 0 1 0 0
Опции подписки
Байт 12 Опции подписки (2) 0 0 0 0 0 0 1 0

Рис. 3‑21. Пример формата байта полезной нагрузки (Payload) пакета SUBSCRIBE.

3.8.4. SUBSCRIBE Actions. Когда Сервер получает пакет SUBSCRIBE от Клиента, Сервер ДОЛЖЕН ответить пакетом SUBACK[MQTT-3.8.4-1]. Пакет SUBACK ДОЛЖЕН иметь один и тот же Packet Identifier, как и подтверждаемый пакет SUBSCRIBE[MQTT-3.8.4-2].

Серверу разрешено начать отправку пакетов PUBLISH, соответствующих подписке, до того, как Сервер пошлет пакет SUBACK.

Если Сервер получил пакет SUBSCRIBE, содержащий Topic Filter, который идентичен Topic Filter не общей подписки (Non‑shared Subscription) для текущей сессии, то он ДОЛЖЕН заменить эту существующую подписку на новую[MQTT-3.8.4-3]. Topic Filter в новой подписке будет идентичен предыдущей подписке, хотя опции у новой подписки (Subscription Options) могут быть другие. Если опция Retain Handling равна 0, то любые существующие сохраненные сообщения (retained messages), попадающие под Topic Filter, ДОЛЖНЫ быть отправлены повторно, но Applicaton Messages НЕ ДОЛЖНЫ быть потеряны из-за замены подписки[MQTT-3.8.4-4].

Если Сервер получил Non‑shared Topic Filter, который не идентичен любому Topic Filter для текущей сессии, то создается новая не общая подписка (Non-shared Subscription). Если опция Retain Handling не равна 2, то все соответствующие фильтру retained messages отправляются Клиенту.

Если Сервер получил Topic Filter, который идентичен Topic Filter для общей подписки (Shared Subscription), которая уже существует на Сервере, то сессия добавляется как подписчик для этой общей подписки. No retained messages are sent.

Если Сервер получил Topic Filter общей подписки (Shared Subscription), который идентичен любому Topic Filter существующей подписки, то создается новая общая подписка (Shared Subscription). Сессия добавляется как подписчик в эту общую подписку. Retained messages не отправляются.

См. секцию 4.8 для дополнительной информации по общим подпискам (Shared Subscriptions).

Если Сервер получил пакет SUBSCRIBE, который содержит несколько Topic Filters, то он ДОЛЖЕН обработать этот пакет, как если бы это была последовательность из нескольких пакетов SUBSCRIBE, за исключением того, что ответы на эти пакеты комбинируются в один ответ SUBACK[MQTT-3.8.4-5].

Пакет SUBACK, отправляемый Сервером Клиенту, ДОЛЖЕН содержать Reason Code для каждой пары фильтр темы / опция подписки (Topic Filter/Subscription Option)[MQTT-3.8.4-6]. Этот Reason Code ДОЛЖЕН либо показывать максимальный уровень QoS, который был предоставлен для этой подписки, или показывать, что подписка потерпела неудачу[MQTT-3.8.4-7]. Сервер может предоставить уровень ниже Maximum QoS, чем запросил подписчик. QoS сообщений приложения (Application Messages) посылаемый в ответ на подписку, ДОЛЖЕН быть минимальным QoS оригинального опубликованного сообщения, и Maximum QoS, предоставленным Сервером[MQTT-3.8.4-8]. Серверу разрешено послать подписчику дублированные копии сообщения в случае, когда оригинальное сообщение было опубликовано с QoS1, и предоставленный максимум QoS был QoS0.

Замечания:

1. Если подписывающемуся Клиенту предоставлен максимальный QoS1 для определенного Topic Filter, то QoS0 Application Message, соответствующее фильтру, доставляется Клиенту с QoS0. Это означает, что Клиент получит не более одной копии сообщения. С другой стороны, сообщение QoS2, опубликованное в ту же тему, понижается Сервером до уровня QoS1 для доставки Клиенту, так что Клиент может получить дублированные копии сообщения.
2. Если подписывающемуся Клиенту предоставлен максимальный QoS0, то оригинальное сообщение, которое было опубликовано как QoS2, может для Клиента потеряться на транзитном участке, однако Сервер никогда не будет посылать дубликат сообщения. Сообщение QoS1, опубликованное в ту же тему, может либо быть потерянным, либо продублированным при передаче Клиенту.
3. Подписка на Topic Filter с QoS2 эквивалентна высказыванию "Я хотел бы получать сообщения, соответствующие этому фильтру, с QoS, с которым они были опубликованы". Это означает, что публишер отвечает за определения максимального QoS, в котором может быть доставлено сообщение, однако подписчик может потребовать, чтобы Сервер понизил уровень QoS до более подходящего для использования уровня.

Идентификаторы подписки (Subscription Identifiers) являются частью состояния сессии (Session State) на Сервере, и они возвращаются Клиенту, который принимает соответствующий подписке пакет PUBLISH. Они удаляются из Session State Сервера, когда Сервер получил пакет UNSUBSCRIBE, когда Сервер получил пакет SUBSCRIBE от Клиента с тем же самым Topic Filter, но с другим Subscription Identifier или без Subscription Identifier, или когда серер послал Session Present 0 в пакете CONNACK.

Идентификаторы подписки не формируют часть Session State на Клиенте. В полезной реализации Клиент будет связывать Subscription Identifiers с другим состоянием на стороне Клиента, это состояние обычно удаляется, когда Клиент отписывается, когда Клиент пописывается на тот же Topic Filter с другим идентификатором или без идентификатора, или когда Клиент получил Session Present 0 в пакете CONNACK.

Серверу не требуется использовать один и тот же набор идентификаторов подписки (Subscription Identifiers) в повторно передаваемом пакете PUBLISH. Клиент может пересоздать подписку путем отправки пакета SUBSCRIBE, который содержит Topic Filter, идентичный Topic Filter существующей подписки в текущей сессии. Если Клиент делает подписку заново после начальной передачи пакета PUBLISH, и использует другой Subscription Identifier, то Серверу разрешено использовать идентичикаторы из первой передачи или повторной передачи. Альтернативно Серверу разрешено использовать новые идентификаторы во время повторной передачи. Серверу не разрешается вернуть старый идентификатор после того, как было отправлен пакет PUBLISH с новым идентификатором.

Примеры сценариев использования, для иллюстрации идентификаторов подписки.

· Реализация Клиента показывает через свой программный интерфейс, что публикация соответствует больше чем одной подписке. Реализация Клиента генерирует новый идентификатор каждый раз, когда делается подписка. Если возвращенная публикация несет в себе больше одного идентификатора подписки, то публикация совпадает больше одной подписке.
· Реализация Клиента позволяет позволяет подписчику направлять сообщения в callback, связанный с подпиской. Реализация Клиента генерирует идентификатор, который уникально отображает идентификатор на callback. Когда получена публикация, она использует идентификатор подписки, чтобы определить, какой callback запустится.
· Реализация Клиента возвратить строку темы, используемую при создании подписки для приложения, когда она доставляет опубликованное сообщение. Чтобы достичь этого результата, Клиент генерирует идентификатор, который уникально идентифицирует Topic Filter. Когда публикция принята, реализация Клиента использует идентификаторы, чтобы найти оригинальные фильтры тем (Topic Filters), и возвратить их приложению Клиента.
· Шлюз перенаправляет публикации от Сервера Клиентам, которые делают подписки на шлюзе. Рализация шлюза поддерживает отображение каждого уникального принятого Topic Filter на набор пар ClientID / Subscription Identifier, которые также принимаются. Он генерирует уникальный идентификатор для каждого Topic Filter, который перенаправляет на Сервер. Когда публикация принята, шлюз использует идентификаторы подписки, полученные им от Сервера, чтобы найти связанные с ними пары Client Identifier / Subscription Identifier. Он добавляет их к пакетам PUBLISH, которые отправляются Клиентам. Если upstream-Сервер послал несколько пакетов PUBLISH, потому что сообщение соответствует нескольким подпискам, то это поведение зеркально отображается Клиентам.

3.9. SUBACK – Subscribe acknowledgement.

Пакет SUBACK отправляется Сервером Клиенту, чтобы подтвердить прием и обработку пакета SUBSCRIBE.

Пакет SUBACK содержит список кодов причины (Reason Codes), которые указывают максимальный уровень QoS, который был предоставлен, или ошибку, которая была обнаружена, для каждой подписки, которая была запрошена пакетом SUBSCRIBE.

3.9.1. SUBACK Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (9) Зарезервировано
  1 0 0 1 0 0 0 0
Байт 2 Remaining Length

Рис. 3‑22. Fixed Header пакета SUBACK.

Remaining Length. Это поле длина Variable Header плюс длина полезной нагрузки (Payload), закодированные как Variable Byte Integer.

3.9.2. SUBACK Variable Header. Variable Header пакета SUBACK содержит поля в следующем порядке: идентификатор пакета из подтверждаемого пакета SUBSCRIBE (Packet Identifier), и свойства (Properties).

3.9.2.1. SUBACK Properties.

3.9.2.1.1. Property Length. Длина свойств в Variable Header пакета SUBACK, закодированная как Variable Byte Integer.

3.9.2.1.2. Reason String. 31 (0x1F), идентификатор Reason String.

Далее идет строка (UTF-8 Encoded String), представляющая причину, связанную с этим ответом. Эта Reason String является удобочитаемой строкой, разработанной для целей диагностики, и она НЕОБЯЗАТЕЛЬНО ДОЛЖНА быть обработана парсингом Клиента.

Сервер использует это значение, чтобы предоставить дополнительную информацию Клиенту. Сервер НЕ ДОЛЖЕН посылать это свойство, если отправка приведет к увеличению размера пакета SUBACK свыше Maximum Packet Size указанного Клиентом[MQTT-3.9.2-1]. Если Reason String указано больше одного раза, то это Protocol Error.

3.9.2.1.3. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной диагностики или передачи другой информации. Сервер НЕ ДОЛЖЕН посылать это свойство, если отправка приведет к увеличению размера пакета SUBACK свыше Maximum Packet Size, указанного Клиентом[MQTT-3.9.2-2]. User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

Бит 7 6 5 4 3 2 1 0
Байт 1 MSB Packet Identifier
Байт 2 LSB Packet Identifier

Рис. 3‑23. Variable Header пакета SUBACK.

3.9.3. SUBACK Payload. Это полезная нагрузка, где содержится список Reason Codes. Каждый Reason Code соответствует Topic Filter подтверждаемого пакета SUBSCRIBE. Порядок следования Reason Codes в пакете SUBACK ДОЛЖЕН должен совпадать с порядком следования Topic Filters в пакете SUBSCRIBE[MQTT-3.9.3-1].

Таблица 3‑8. Subscribe Reason Codes.

Dec Hex Имя Reason Code Описание
0 0x00 Предоставлено QoS0 Подписка принимается, и максимальное количество отправленных QoS равно QoS 0. Это может быть ниже QoS, чем было запрошено.
1 0x01 Предоставлено QoS1 Подписка принимается, и максимальное количество отправленных QoS равно QoS 1. Это может быть ниже QoS, чем было запрошено.
2 0x02 Предоставлено QoS2 Подписка принимается, и все полученные QoS отправляются на эту подписку.
128 0x80 Неопределенная ошибка Подписка не принимается, и Сервер либо не желает раскрывать причину, либо не применимы никакие другие Reason Code.
131 0x83 Ошибка, специфичная для реализации Пакет SUBSCRIBE сформирован корректно, но сервер не принимает его.
135 0x87 Не авторизовано Клиент не авторизован для создания этой подписки.
143 0x8F Недопустимый Topic Filter Фильтр темы сформирован правильно, но не разрешен для данного Клиента.
145 0x91 Packet Identifier уже используется Указанный идентификатор пакета уже используется.
151 0x97 Превышена квота Превышен предел, который может обработать реализация, либо наложено административное ограничение.
158 0x9E Общие подписки не поддерживаются Сервер не поддерживает Shared Subscriptions для этого Клиента.
161 0xA1 Идентификаторы подписки не поддерживаются Сервер не поддерживает идентификаторы подписки; подписка не принимается.
162 0xA2 Wildcard подписки не поддерживаются Сервер не поддерживает Wildcard Subscriptions; подписка не принимается.

Сервер, отправляющий пакет SUBACK, ДОЛЖЕН использовать Subscribe Reason Codes для каждого принятого Topic Filter[MQTT-3.9.3-2].

Замечание: здесь всегда используется один Reason Code для каждого фильтра темы (Topic Filter) в соответствующем пакете SUBSCRIBE. Если Reason Code не специфичен для фильтров тем (такой как 0x91 (Packet Identifier in use)), то он устанавливается для каждого фильтра темы.

3.10. UNSUBSCRIBE – Unsubscribe request.

Пакет UNSUBSCRIBE отправляется Клиентом Серверу, чтобы отписаться от тем.

3.10.1. UNSUBSCRIBE Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (10) Зарезервировано
  1 0 1 0 0 0 1 0
Байт 2 Remaining Length

Рис. 3.28. Fixed Header пакета UNSUBSCRIBE.

Биты 3, 2, 1 и 0 в Fixed Header пакета UNSUBSCRIBE зарезервированы, и ДОЛЖНЫ быть установлены в 0, 0, 1 и 0 соответственно. Сервер ДОЛЖЕН обрабатывать любое другое значение этих бит как ошибку, и закрывать сетевое соединение[MQTT-3.10.1-1].

Remaining Length. Это поле показывает длину Variable Header (2 байта) плюс длина Payload, закодированные как Variable Byte Integer.

3.10.2. UNSUBSCRIBE Variable Header. Variable Header пакета UNSUBSCRIBE содержит поля в следующем порядке: идентификатор пакета (Packet Identifier) и свойства (Properties). Секция 2.2.1 предоставляет больше информации об идентификаторах пакета. Правила для кодирования свойств описаны в секции 2.2.2.

3.10.2.1. UNSUBSCRIBE Properties.

3.10.2.1.1. Property Length. Это длина свойств в Variable Header пакета UNSUBSCRIBE, закодированная как Variable Byte Integer.

3.10.2.1.2. User Property. 38 (0x26) Byte, идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

Замечание: User Properties пакета UNSUBSCRIBE может использоваться для отправки связанных с подпиской свойств от Клиента Серверу. Смысл свойств пользователя не определяется этой спецификацией.

3.10.3. UNSUBSCRIBE Payload. Это полезная нагрузка пакета UNSUBSCRIBE содержит список фильтров тем (Topic Filters), от которых Клиент хочет отписаться. Topic Filters в пакете UNSUBSCRIBE ДОЛЖЕН быть строкой (UTF-8 Encoded Strings)[MQTT-3.10.3-1], как это определено в секции 1.5.4, упакованной непрерывно.

Полезная нагрузка пакета UNSUBSCRIBE ДОЛЖНА содержать как минимум один Topic Filter[MQTT-3.10.3-2]. Пакет UNSUBSCRIBE без полезной нагрузки это Protocol Error. См. секцию 4.13 для информации по обработке ошибок.

Рис. 3.30 показывает пример полезной нагрузки для пакета UNSUBSCRIBE с двумя фильтрами тем (Topic Filters) "a/b" и "c/d".

  Описание 7 6 5 4 3 2 1 0
Фильтр темы (Topic Filter)
Байт 1 MSB длины (0) 0 0 0 0 0 0 0 0
Байт 2 LSB длины (3) 0 0 0 0 0 0 1 1
Байт 3 'a' (0x61) 0 1 1 0 0 0 0 1
Байт 4 '/' (0x2F) 0 0 1 0 1 1 1 1
Байт 5 'b' (0x62) 0 1 1 0 0 0 1 0
Фильтр темы
Байт 6 MSB длины (0) 0 0 0 0 0 0 0 0
Байт 7 LSB длины (3) 0 0 0 0 0 0 1 1
Байт 8 'c' (0x63) 0 1 1 0 0 0 1 1
Байт 9 '/' (0x2F) 0 0 1 0 1 1 1 1
Байт 10 'd' (0x64) 0 1 1 0 0 1 0 0

Рис. 3.30. Формат байт полезной нагрузки пакета UNSUBSCRIBE.

3.10.4. UNSUBSCRIBE Actions. Фильтры тем Topic Filters (которые либо содержат символы wildcard, либо нет), предоставленные в пакете UNSUBSCRIBE ДОЛЖНЫ быть посимвольно сравнены для Клиента с текущим набором фильтров тем, хранящихся на Сервере. Если любой фильтр точно соответствует, то владеющая им подписка ДОЛЖНА быть удалена[MQTT-3.10.4-1], в противном случае не выполняется никакая дополнительная обработка.

Когда Сервер принял UNSUBSCRIBE:

· Он ДОЛЖЕН остановить добавление для доставки Клиенту любых новых сообщений, которые соответствуют фильтрам тем[MQTT-3.10.4-2].
· Он ДОЛЖЕН завершить доставку любых сообщений QoS1 или QoS2, которые соответствуют фильтрам, и начать их отправку Клиенту[MQTT-3.10.4-3].
· Он МОЖЕТ продолжить доставку существующих сообщений, которые были буферизированы для доставки Клиенту.

Сервер ДОЛЖЕН ответить на запрос UNSUBSCRIBE отправкой пакета UNSUBACK[MQTT-3.10.4-4]. Пакет UNSUBACK ДОЛЖЕН должен иметь такой же идентификатор пакета (Packet Identifier) как и пакет UNSUBSCRIBE. Даже когда ни одна из подписок на тему не была удалена, Сервер ДОЛЖЕН должен ответить пакетом UNSUBACK[MQTT-3.10.4-5].

Если Сервер принимает пакет UNSUBSCRIBE, который содержит несколько фильтров тем (Topic Filters), то он ДОЛЖЕН обработать такой пакет так, как если бы были приняты несколько пакетов UNSUBSCRIBEs, лишь с тем отличием, что в ответ будет послан только один UNSUBACK[MQTT-3.10.4-6].

Если Topic Filter представляет общую подписку (Shared Subscription), то эта сессия отсоединяется от общей подписки. Если эта сессия была единственной сессией, с которой была связана общая подписка, то эта общая подписка удаляется. См. секцию 4.8.2 для описания обработки общей подписки (Shared Subscription).

3.11. UNSUBACK – Unsubscribe acknowledgement. Пакет UNSUBACK отправляется Сервером для подтверждения приема пакета UNSUBSCRIBE.

3.11.1. UNSUBACK Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (11) Зарезервировано
  1 0 1 1 0 0 0 0
Байт 2 Remaining Length

Рис. 3.31. Fixed Header пакета UNSUBACK.

Remaining Length. Это поле показывает длину Variable Header плюс длина Payload, закодированные как Variable Byte Integer.

3.11.2. UNSUBACK Variable Header. Variable Header пакетп UNSUBACK содержит поля в следующем порядке: Packet Identifier (идентификатор пакета) из подтверждаемого пакета UNSUBSCRIBE, и Properties (свойства). Правила для кодирования свойств описаны в секции 2.2.2.

Бит 7 6 5 4 3 2 1 0
Байт 1 MSB Packet Identifier
Байт 2 LSB Packet Identifier

Рис. 3.32. Variable Header пакета UNSUBACK.

3.11.2.1. UNSUBACK Properties.

3.11.2.1.1. Property Length. Длина свойств в Variable Header пакета UNSUBACK, закодированная как Variable Byte Integer.

3.11.2.1.2. Reason String. 31 (0x1F), идентификатор Reason String.

Далее идет строка (UTF-8 Encoded String), представляющая причину, связанную с этим ответом. Эта Reason String является удобочитаемой строкой, разработанной для целей диагностики, и она НЕОБЯЗАТЕЛЬНО ДОЛЖНА быть обработана парсингом Клиента.

Сервер использует это значение для предоставления Клиенту дополнительной информации. Сервер НЕ ДОЛЖЕН посылать это свойство, если отправка приведет к увеличению размера пакет UNSUBACK сверх Maximum Packet Size, указанного Клиентом[MQTT-3.11.2-1]. Если Reason String указано больше одного раза, то это Protocol Error.

3.11.2.1.3. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной диагностики или передачи другой информации. Сервер НЕ ДОЛЖЕН посылать это свойство, если отправка приведет к увеличению размера пакета UNSUBACK сверх Maximum Packet Size, указанного Клиентом[MQTT-3.11.2-2]. User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

3.11.3. UNSUBACK Payload. Полезная нагрузка, содержащая список Reason Codes. Каждый Reason Code соответствует Topic Filter в подтверждаемом пакете UNSUBSCRIBE. Порядок следования Reason Codes в пакете UNSUBACK ДОЛЖЕН совпадать с порядком следования Topic Filters в пакете UNSUBSCRIBE[MQTT-3.11.3-1].

Значения без знака для одного байта кодов причины отписки (Unsubscribe Reason Codes) показаны в таблице ниже. Сервер, посылающий пакет UNSUBACK, ДОЛЖЕН использовать одно из значений Unsubscribe Reason Code для каждого принятого Topic Filter[MQTT-3.11.3-2].

Таблица 3‑9. Unsubscribe Reason Codes.

Dec Hex Имя Reason Code Описание
0 0x00 Успешное завершение Подписка удалена.
17 0x11 Подписка не существует Нет совпадающего Topic Filter, используемого Клиентом
128 0x80 Неопределенная ошибка Отписка не может быть завершена, и Сервер либо не желает раскрывать причину, либо не применимы никакие другие Reason Code.
131 0x83 Ошибка, специфичная для реализации Пакет UNSUBSCRIBE сформирован корректно, но сервер не принимает его.
135 0x87 Не авторизовано Клиент не авторизован для отписки.
143 0x8F Недопустимый Topic Filter Фильтр темы сформирован правильно, но не разрешен для данного Клиента.
145 0x91 Packet Identifier уже используется Указанный идентификатор пакета уже используется.

Замечание: существует всегда только один Reason Code для каждого Topic Filter в соответствующем пакете UNSUBSCRIBE. Если Reason Code не специфичен для фильтров тем (такой как 0x91 (Packet Identifier in use)), то он устанавливается для каждого Topic Filter.

3.12. PINGREQ – PING request. Пакет PINGREQ отправляется от Клиента Серверу. Он может использоваться для следующего:

· Показать Серверу, что Клиент находится в работоспособном состоянии, когда отсутствуют какие-либо другие пакеты (MQTT Control Packet), посылаемые от Клиента к Серверу.
· Запрос Серверу, что он отвечает и находится в работоспособном состоянии.
· Проверить сеть, чтобы показать, что сетевое соединение работоспособно.

Этот пакет используется в обработке Keep Alive, подробности см. в секции 3.1.2.10.

3.12.1. PINGREQ Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (12) Зарезервировано
  1 1 0 0 0 0 0 0
Байт 2 Remaining Length (0)
  0 0 0 0 0 0 0 0

Рис. 3.33. Fixed Header пакета PINGREQ.

3.12.2. PINGREQ Variable Header. У пакета PINGREQ нет Variable Header.

3.12.3. PINGREQ Payload. У пакета PINGREQ нет полезной нагрузки.

3.12.4. PINGREQ Actions. Сервер ДОЛЖЕН послать пакет PINGRESP в ответ на пакет PINGREQ[MQTT-3.12.4-1].

3.13. PINGRESP – PING response.

Пакет PINGRESP отправляется Сервером Клиенту в ответ на пакет PINGREQ. Это показывает, что Сервер находится в работоспособном состоянии.

Этот пакет используется в обработке Keep Alive, подробности см. в секции 3.1.2.10.

3.13.1. PINGRESP Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (13) Зарезервировано
  1 1 0 1 0 0 0 0
Байт 2 Remaining Length (0)
  0 0 0 0 0 0 0 0

Рис. 3.34. Fixed Header пакета PINGRESP.

3.13.2. PINGRESP Variable Header. У пакета PINGRESP нет Variable Header.

3.13.3. PINGRESP Payload. У пакета PINGRESP нет полезной нагрузки.

3.13.4. PINGRESP Actions. При получании PINGRESP Клиент не осущесвляет никаких дейсвий.

3.14. DISCONNECT – Disconnect notification. Пакет DISCONNECT это последний пакет протокола (MQTT Control Packet), который отправляется от Клиента Серверу. Он показывает причину закрытия сетевого соединения. Клиент или Сервер МОЖЕТ отправить пакет DISCONNECT перед закрытием сетевого соединения. Если сетевое соединение закрыто без предварительной отправки пакета DISCONNECT с Reason Code 0x00 (Normal disconnection), и у соединение есть Will Message, то Will Message публикуется. Подробнее см. в секции 3.1.2.5.

Сервер НЕ ДОЛЖЕН посылать пакет DISCONNECT, пока он не отправит CONNACK с Reason Code меньше 0x80[MQTT-3.14.0-1].

3.14.1. DISCONNECT Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (14) Зарезервировано
  1 1 1 0 0 0 0 0
Байт 2 Remaining Length

Рис. 3.35. Fixed Header пакета DISCONNECT.

Клиент или Сервер ДОЛЖЕН проверить, что зарезервированные биты установлены в 0. Если они ненулевые, то они посылают пакет DISCONNECT с Reason code 0x81 (Malformed Packet), как это описано в секции 4.13[MQTT-3.14.1-1].

Remaining Length. В этом поле находится длина Variable Header, закодированная как Variable Byte Integer.

3.14.2. DISCONNECT Variable Header. Variable Header пакета DISCONNECT содержит поля в следующем порядке: Disconnect Reason Code (код причины разъединения) и Properties (свойства). Правила для кодирования свойств описаны в секции 2.2.2.

3.14.2.1. Disconnect Reason Code. Байт 1 в Variable Header это Disconnect Reason Code. Если Remaining Length меньше 1, то подразумевается значение 0x00 (Normal disconnection).

Значения без знака для одного байта Disconnect Reason Code показаны в таблице ниже.

Таблица 3‑10. Значения Disconnect Reason Code.

Dec Hex Имя Reason Code Кто отправляет Описание
0 0x00 Нормальное отключение Клиент или Сервер Нормальное закрытие соединения. Will Message отправляться не будет.
4 0x04 Отключение с Will Message Клиент Клиент хочет отключиться, но требует, чтобы Сервер также опубликовал Will Message.
128 0x80 Неопределенная ошибка Клиент или Сервер Соединение закрыто, но отправитель либо не хочет раскрывать причину, либо для причины не подходит ни один из Reason Code.
129 0x81 Malformed Packet Клиент или Сервер Полученный пакет не удовлетворяет этой спецификации.
130 0x82 Protocol Error Клиент или Сервер Принят неожиданный пакет, либо не соблюден порядок следования пакетов.
131 0x83 Ошибка, специфичная для реализации Клиент или Сервер Принятый пакет сформирован правильно, но не может быть обработан этой реализацией.
135 0x87 Не авторизовано Сервер Запрос не авторизован
137 0x89 Сервер занят Сервер Сервер занят, и не может принимать запросы от этого Клиента
139 0x8B Завершение работы сервера Сервер Сервер завершает работу.
141 0x8D Таймаут Keep Alive Сервер Соединение закрыто, потому что в течение 1.5 * (Keep Alive) от Клиента не поступило ни одного пакета.
142 0x8E Session taken over Сервер Подключено другое соединение, использующее тот же ClientID, что приводит к закрытию этого соединения.
143 0x8F Недопустимый Topic Filter Сервер Фильтр темы сформирован корректно, но не может быть принят этим Сервером.
144 0x90 Недопустимое Topic Name Клиент или Сервер Имя темы сформировано правильно, но не может быть принято этим Клиентом или Сервером.
147 0x93 Превышен Receive Maximum Клиент или Сервер Клиент или Сервер принял больше чем Receive Maximum публикаций, для которых не отправлены PUBACK или PUBCOMP.
148 0x94 Недопустимый Topic Alias Клиент или Сервер Клиент или Сервер принял пакет PUBLISH, содержащий значение Topic Alias, который больше чем Maximum Topic Alias, отправленный в пакете CONNECT или CONNACK.
149 0x95 Пакет слишком большой Клиент или Сервер Размер пакета больше, чем Maximum Packet Size для этого Клиента или Сервера.
150 0x96 Частота выдачи сообщений слишком большая Клиент или Сервер Частота поступления данных слишком большая.
151 0x97 Превышена квота Клиент или Сервер Превышен предел, который может обработать эта реализация, или превышено административное ограничение.
152 0x98 Административное действие Клиент или Сервер Соединение закрыто из-за административного действия.
153 0x99 Недопустимый формат полезной нагрузки Клиент или Сервер Формат полезной нагрузки не соответствует указанному Payload Format Indicator.
154 0x9A Retain не поддерживается Сервер Сервер не поддерживает сохраненные сообщения.
155 0x9B QoS не поддерживается Сервер Клиент указал QoS больше, чем было указано QoS в Maximum QoS пакета CONNACK.
156 0x9C Используйте другой сервер Сервер Клиент временно должен использовать другой Сервер.
157 0x9D Сервер перемещен Сервер Клиент должен постоянно использовать другой Сервер.
158 0x9E Общие подписки не поддерживаются Сервер Сервер не поддерживает Shared Subscriptions.
159 0x9F Превышена частота подключений Сервер Соединение закрыто из-за слишком большой частоты подключений.
160 0xA0 Максимальное время подключения Сервер Превышено максимально допустимое время для этого подключения.
161 0xA1 Идентификаторы подписки не поддерживаются Сервер Сервер не поддерживает Subscription Identifiers; подписка не принята.
162 0xA2 Wildcard подписки не поддерживаются Сервер Сервер не поддерживает Wildcard Subscriptions; подписка не принята.

Клиент или Сервер, посылающий пакет DISCONNECT, ДОЛЖЕН использовать одно из значений DISCONNECT Reason Code[MQTT-3.14.2-1]. Reason Code и Property Length могут быть опущены, если Reason Code 0x00 (Normal disconnection), и свойства отсутствуют Properties. В этом случае у пакета DISCONNECT значение Remaining Length равно 0.

Замечания:

1. Пакет DISCONNECT используется для того, чтобы показать причину отключения для случаев, когда не нужно посылать пакет подтверждения (таких как публикация QoS0), или когда Клиент или Сервер не может продолжить обрабатывать соединение.
2. Информация может использоваться Клиентом для принятия решения о том, следует ли пытаться восстановить соединение, и как долго надо ждать перед повторными попытками установления соединения.

3.14.2.2. DISCONNECT Properties.

3.14.2.2.1. Property Length. Это длина свойств в Variable Header пакета DISCONNECT, закодированная как Variable Byte Integer. Если значение Remaining Length меньше 2, то используется значение 0.

3.14.2.2.2. Session Expiry Interval. 17 (0x11), идентификатор Session Expiry Interval.

За ним идет 4-байтное целое Four Byte Integer, представляющее оставшийся интервал времени жизни сессии (Session Expiry Interval) в секундах. Если Session Expiry Interval подключено больше одного раза, то это Protocol Error.

Если Session Expiry Interval отсутствует, то используется Session Expiry Interval в пакете CONNECT.

Session Expiry Interval НЕ ДОЛЖЕН отправляться Сервером в пакете DISCONNECT[MQTT-3.14.2-2].

Если Session Expiry Interval в пакете CONNECT равен 0, то будет Protocol Error, если устанавливать не нулевой Session Expiry Interval в пакете DISCONNECT, который посылается Клиентом. Если такой ненулевой Session Expiry Interval принимается Сервером, то он не обработает его как допустимый пакет DISCONNECT. Сервер использует DISCONNECT с Reason Code 0x82 (Protocol Error), как описано в секции 4.13.

3.14.2.2.3. Reason String. 31 (0x1F), идентификатор Reason String.

За ним идет строка (UTF-8 Encoded String), представляющая причину отключения. Reason String это удобочитаемая строка, разработанная для диагностики, она НЕОБЯЗАТЕЛЬНО ДОЛЖНА быть обработана получателем.

Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета DISCONNECT свыше Maximum Packet Size, указанного получателем[MQTT-3.14.2-3]. Если Reason String указано больше одного раза, то это Protocol Error.

3.14.2.2.4. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной диагностики или другой информации. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета DISCONNECT свыше Maximum Packet Size, указанного получателем[MQTT-3.14.2-4]. User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

3.14.2.2.5. Server Reference. 28 (0x1C), идентификатор Server Reference.

За ним идет строка (UTF-8 Encoded String), которая может использоваться Клиентом для идентификации другого Сервера для использования. Если Server Reference указано больше одного раза, то это Protocol Error.

Сервер посылает пакет DISCONNECT, включающий Server Reference и Reason Code 0x9C (Use another server) или 0x9D (Server moved), как описано в секции 4.13.

См. секцию 4.11 с описанием Server Redirection для информации, как используется Server Reference.

  Описание 7 6 5 4 3 2 1 0
Disconnect Reason Code
Байт 1   0 0 0 0 0 0 0 0
Properties
Байт 2 Длина (5) 0 0 0 0 0 1 0 1
Байт 3 Session Expiry Interval identifier (17) 0 0 0 1 0 0 0 1
Байт 4 Session Expiry Interval (0) 0 0 0 0 0 0 0 0
Байт 5 0 0 0 0 0 0 0 0
Байт 6 0 0 0 0 0 0 0 0
Байт 7 0 0 0 0 0 0 0 0

Рис. 3‑24. Пример Variable Header пакета DISCONNECT.

3.14.3. DISCONNECT Payload. У паета DISCONNECT нет полезной нагрузки.

3.14.4. DISCONNECT Actions. Сервер после отправки пакета DISCONNECT:

· Больше НЕ ДОЛЖЕН посылать никакие пакеты (MQTT Control Packets) на этом сетевом соединении[MQTT-3.14.4-1].
· ДОЛЖЕН закрыть сетевое соединение Network Connection[MQTT-3.14.4-2].

Сервер при приеме пакета DISCONNECT с Reason Code 0x00 (Success):

· ДОЛЖЕН отбросить любые Will Message, связанные с текущим соединением без их публикации[MQTT-3.14.4-3], как это описано в секции 3.1.2.5.

Получатель при приеме пакета DISCONNECT:

· МОЖЕТ закрыть сетевое соединение.

3.15. AUTH – Authentication exchange. Пакет AUTH отправляется от Клиента Серверу или от Сервера Клиенту как часть расширенного обмена аутентификации (extended authentication exchange), такого как аутентификация вызова/ответа (challenge/response). Будет ошибкой Protocol Error для Клиента или Сервера отправлять пакет AUTH, если пакет CONNECT не содержит такой же метод аутентификации (Authentication Method).

3.15.1. AUTH Fixed Header.

Бит 7 6 5 4     3         2         1         0    
Байт 1 Тип MQTT Control Packet (15) Зарезервировано
  1 1 1 1 0 0 0 0
Байт 2 Remaining Length

Рис. 3.35. Fixed Header пакета AUTH.

Биты 3, 2, 1 и 0 в Fixed Header пакета AUTH и ДОЛЖНЫ быть все установлены в 0. Клиент или Сервер ДОЛЖЕН обрабатывать любое другое значение этих бит как неправильно сформированный пакет, и закрывать сетевое соединение[MQTT-3.15.1-1].

Remaining Length. В этом поле находится длина Variable Header, закодированная как Variable Byte Integer.

3.15.2. AUTH Variable Header. Variable Header пакета AUTH Packet содержит поля в следующем порядке: Authenticate Reason Code (код причины аутентификации) и Properties (свойства). Правила для кодирования свойств описаны в секции 2.2.2.

3.15.2.1. Authenticate Reason Code. Байт 0 в Variable Header это Authenticate Reason Code. Это значения без знака в виде одного байта, показанные в таблице ниже. Отправитель пакета AUTH ДОЛЖЕН использовать один из Authenticate Reason Codes[MQTT-3.15.2-1].

Таблица 3‑11. Authenticate Reason Codes.

Dec Hex Имя Reason Code Кто отправляет Описание
0 0x00 Успех Сервер Аутентификация прошла успешно.
24 0x18 Продолжение аутентификации Клиент или Сервер Аутентификация переходит к следующему шагу.
25 0x19 Повторная аутентификация Клиент Инициирование повторной аутентификации.

Reason Code и Property Length могут быть опущены, если Reason Code 0x00 (Success), и здесь нет свойств Properties. В этом случае у пакетов AUTH значение Remaining Length равно 0.

3.15.2.2. AUTH Properties.

3.15.2.2.1. Property Length. Длина свойств в Variable Header пакета AUTH, закодированная как Variable Byte Integer.

3.15.2.2.2. Authentication Method. 21 (0x15), идентификатор Authentication Method.

За ним идет строка (UTF-8 Encoded String), содержащая имя метода аутентификации. Если Authentication Method указано больше одного раза, то это Protocol Error. См. секцию 4.12 для дополнительной информации о расширенной идентификации.

3.15.2.2.3. Authentication Data. 22 (0x16), идентификатор Authentication Data.

За ним идут двоичные данные (Binary Data), содержащие данные аутентификации. Если Authentication Data указано больше одного раза, то это Protocol Error. Содержимое этих данных определяется методом аутентификации. См. секцию 4.12 для дополнительной информации о расширенной идентификации.

3.15.2.2.4. Reason String. 31 (0x1F), идентификатор Reason String.

За ним идет строка (UTF-8 Encoded String), представляющая причину для отключения. Reason String это удобочитаемая строка, разработанная для диагностики, она НЕОБЯЗАТЕЛЬНО ДОЛЖНА быть обработана получателем.

Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета AUTH свыше Maximum Packet Size, указанного получателем[MQTT-3.15.2-2]. Если Reason String указано больше одного раза, то это Protocol Error.

3.15.2.2.5. User Property. 38 (0x26), идентификатор User Property.

За ним идет пара строк (UTF-8 String Pair). Это свойство может использоваться для предоставления дополнительной диагностики или другой информации. Отправитель НЕ ДОЛЖЕН посылать это свойство, если его отправка приведет к увеличению размера пакета AUTH свыше Maximum Packet Size, указанного получателем[MQTT-3.15.2-3]. User Property может появляться несколько раз для предоставления нескольких пар имя-значение (name-value). Одно и то же имя также может появляться несколько раз.

3.15.3. AUTH Payload. У пакета AUTH нет полезной нагрузки.

3.15.4. AUTH Actions. См. секцию 4.12 для дополнительной информации о расширенной идентификации.

[4. Рабочее поведение]

4.1. Session State. Чтобы организовать алгоритм потока протокола QoS1 и QoS2, Серверу и Клиенту нужно связать текущее состояние протокола с идентификатором Клиента (Client Identifier), эта информация называется состоянием сессии (Session State). Сервер также сохраняет подписки как часть Session State.

Сессия может распространяться на последовательность из нескольких сетевых соединений. Она продолжается до последнего сетевого соединения плюс Session Expiry Interval.

Session State Клиента состоит из следующего:

· Сообщения QoS1 и QoS2, которые отправлены Сервером, но не были полностью подтверждены.
· Сообщения QoS2, которые были приняты от Сервера, но не были полностью подтверждены.

Session State Сервера состоит из следующего:

· Существование сессии, даже если остальная часть Session State пустая.
· Подписки Клиентов, включая любые идентификаторы подписок (Subscription Identifiers).
· Сообщения QoS1 и QoS2, которые отправлены Клиенту, но не были полностью подтверждены.
· Сообщения QoS1 и QoS2, ожидающие передачи для Клиента, и ОПЦИОНАЛЬНО сообщения QoS0, ожидающие передачи для Клиента.
· Сообщения QoS2, которые были получены Клиентом, но не были полностью подтверждены.
· Will Message и Will Delay Interval.
· Если сессия в настоящий момент не имеет соединения, тоо время окончания сессии и Session State будут отброшены.

Сохраненные сообщения (Retained Messages) не формируют часть Session State Сервера, они не удаляются при завершении сессии.

4.1.1. Storing Session State. Клиент и Сервер НЕ ДОЛЖНЫ отбрасывать Session State, пока открыто сетевое соединение[MQTT-4.1.0-1]. Сервер ДОЛЖЕН отбросить Session State, когда сетевое соединение закрыто, и истек интервал времени жизни сессии (Session Expiry Interval)[MQTT-4.1.0-2].

Замечание: конечно, возможности по сохранению информации в реализациях Клиента и Сервера могут иметь свои ограничения по объему, и могут быть подчинены административным политикам. Сохраненное Session State может быть отброшено в результате действия по администрированию, включая автоматизированный ответ на определенные условия. Это приводит к завершению сессии. Эти действия могут быть вызваны ограниченностью ресурсов или другими рабочими причинами. Возможно, что аппаратные или программные сбои могут привести к потере или повреждению Session State, сохраненного Клиентом или Сервером. Разумно оценить возможности по сохранению информации Клиента и Сервера, что они достаточны.

4.1.2. Примеры органзиации хранения Session State.

Например, счетчик электроэнергии может использовать сообщения QoS1, чтобы защитить чтения показаний от потерь информации при передаче по сети. Разработчик этого решения определил, что источник питания достаточно надежен, и в таком случае данные на Клиенте и Сервере можно хранить в обычной, не энергонезависимой памяти, без риска их потери.

И наоборот, поставщик приложения счетчика платежа времени парковки может решить, что платежные сообщения никогда не должны теряться из-за отказов сети или Клиента MQTT. Таким образом это может потребовать сохранять все данные в энергонезависимую память перед тем, как они будут переданы по сети.

4.2. Network Connections. Протокол MQTT требует наличия нижележащего транспорта, который предоставляет упорядоченный, без потерь поток байт от Клиента к Серверу и от Сервера Клиенту. Обычно для транспорта используется проткол TCP/IP, однако эта спецификация MQTT не требует поддержки какого-либо определенного транспортного протокола. Клиент или Сервер МОГУТ поддерживать любой из перечисленных здесь транспортных протоколов, или любой другой транспортный протокол, удовлетворяющий требованиям этой секции стандарта.

Клиент или Сервер ДОЛЖЕН поддерживать один или большее количество нижележащих протоколов транспорта, чтобы предоставить упорядоченную, без потерь среду передачи потока байт между Сервером и Клиентом в обоих направлениях[MQTT-4.2-1].

Замечания:

1. TCP/IP, как это определено в [RFC0793] может использоваться для для MQTT v3.1.1 и MQTT v5.0. Также подойдут следующие транспортные протоколы:

· TLS [RFC5246].
· WebSocket [RFC6455].

2. TCP порты 8883 и 1883 зарегистрированы IANA для обмена MQTT TLS и non-TLS соответственно.

3. Сетевые транспорты без установления соединения, такие как User Datagram Protocol (UDP), не подойдут, поскольку они допускают потерю данных или не упорядоченную их доставку.

4.3. Уровни Quality of Service и управление потоком протокола. MQTT доставляет Application Messages в соответствии с уровнями Quality of Service (QoS), определенными в следующих секциях. Протокол доставки симметричный, в описании далее Клиент и Сервер могут играть роль как отправителя, так и получателя. Протокол доставки касается исключительно доставки сообщения приложения от одного отправителя к одному получателю. Когда Сервер доставляет Application Message больше чем одному Клиенту, он работает с каждым Клиентом независимо. Уровень QoS, используемый для доставки исходящего Application Message Клиенту, может отличаться от уровня входящего Application Message.

4.3.1. QoS0: максимум однократная доставка. Сообщение доставляется в соответствии с возможностями нижележащей сети. Ни один ответ не отправляется получателем, и ни одна повторная попытка не выполняется отправителем. Сообщение поступает получателю либо один раз, либо вообще не поступает (нет гарантии доставки).

В протоколе доставки QoS0 отправитель:

· ДОЛЖЕН послать пакет PUBLISH с QoS0 и флаг DUP, установленный в 0[MQTT-4.3.1-1].

В протоколе доставки QoS0 получатель:

· Принимает право собственности на сообщение, когда получает пакет PUBLISH.

Действие отправителя MQTT Control Packet Действие получателя
PUBLISH QoS 0, DUP=0    
  ---------- >  
    Доставка Application Message соответствующему
получателю (получателям)

Рис. 4.1. Пример диаграммы обработки протокола QoS0.

4.3.2. QoS1: минимум однократная доставка. Уровень Quality of Service гарантирует, что сообщение достигло получателя как минимум один раз. У пакета PUBLISH QoS1 в его Variable Header имеется Packet Identifier, и этот пакет подтверждается пакетом PUBACK. Секция 2.2.1 предоставляет больше информации об идентификаторах пакета.

В протоколе доставки QoS1 отправитель:

· ДОЛЖЕН присвоить не используемый Packet Identifier всякий раз, когда имеется новое Application Message для публикации[MQTT-4.3.2-1].
· ДОЛЖЕН послать пакет PUBLISH, содержащий этот Packet Identifier с QoS1 и флагом DUP, установленным в 0[MQTT-4.3.2-2].
· ДОЛЖЕН обработать пакет PUBLISH как не подтвержденный (unacknowledged), пока не будет принят от получателя соответствущий пакет PUBACK. Обратитесь к секции 4.4 для обсуждения не подтвержденных сообщений[MQTT-4.3.2-3].

Packet Identifier становится доступным для повторного использования, когда отправитель принял пакет PUBACK.

Обратите внимание, что отправителю разрешено посылать последующие пакеты PUBLISH с другими идентификаторами, пока он ожидает подтверждений на ранее отправленные пакеты PUBLISH.

В протоколе доставки QoS1 получатель:

· ДОЛЖЕН ответить пакетом PUBACK, который содержит тот же Packet Identifier, что и был в поступившем подтверждаемом пакете PUBLISH, что означает принятие во владение полученного Application Message[MQTT-4.3.2-4].
· После отпраки пакета PUBACK получатель ДОЛЖЕН обрабатывать любые приходящие пакеты PUBLISH с таким же идентификатором как новые Application Message, независимо от установки в них флага DUP[MQTT-4.3.2-5].

Действие отправителя MQTT Control Packet Действие получателя
Сохранение сообщения    
Отправка PUBLISH QoS 1, DUP=0, < Packet Identifier > ---------- >  
    Инициировать дальнейшую доставку Application Message(1)
  < ---------- Отправка PUBACK < Packet Identifier >
Отбрасывание сообщения    

Рис. 4.2. Пример диаграммы потока протокола QoS1.

Примечание (1): получателю не нужно завершать доставку Application Message перед отправкой PUBACK. Когда его оригинальный отправитель получает пакет PUBACK, владение Application Message передается получателю.

4.3.3. QoS2: доставка точно 1 раз. Это самый высокий уровень качества доставки (Quality of Service), предназначенный для случаев, когда не допускается ни потеря сообщений, ни их дублирование. С QoS2 повышаются накладные расходы на обработку.

У сообщения QoS2 в его Variable Header имеется Packet Identifier. Секция 2.2.1 предоставляет больше информации об идентификаторах пакета. Получатель PUBLISH-пакета QoS2 подтверждает прием в двухшаговом процессе подтверждения.

В протоколе доставки QoS2 отправитель:

· ДОЛЖЕН присвоить не используемый Packet Identifier всякий раз, когда имеется новое Application Message для публикации[MQTT-4.3.3-1].
· ДОЛЖЕН послать пакет PUBLISH, содержащий этот Packet Identifier с QoS2 и флаг DUP, установленный в 0[MQTT-4.3.3-2].
· ДОЛЖЕН обработать пакет PUBLISH как не подтвержденный (unacknowledged), пока не получит соответствующий пакет PUBREC от получателя[MQTT-4.3.3-3]. См. секцию 4.4 для обсуждения не подтвержденных сообщений.
· ДОЛЖЕН послать пакет PUBREL, когда получить пакет PUBREC от получателя со значением Reason Code меньше 0x80. Этот пакет PUBREL ДОЛЖЕН содержать такой же Packet Identifier, как и оригинальный пакет PUBLISH[MQTT-4.3.3-4].
· ДОЛЖЕН обработать пакет PUBREL как не подтвержденный (unacknowledged), пока не будет получен соответствующий пакет PUBCOMP от получателя[MQTT-4.3.3-5].
· НЕ ДОЛЖЕН повторно посылать PUBLISH после отправки соответствующего пакета PUBREL[MQTT-4.3.3-6].
· НЕ ДОЛЖЕН применять истечения сообщения (Message expiry), если был отправлен пакет PUBLISH[MQTT-4.3.3-7].

Packet Identifier становится доступным для повторного использования, как только отправитель получил пакет PUBCOMP или пакет PUBREC с Reason Code 0x80 или больше.

Обратите внимание, что отправителю разрешено передавать последующие пакеты PUBLISH с другими идентификаторами, пока он ожидает подтверждение получения ранее отправленных пакетов, попадающих под управление потоком, как это описано в секции 4.9.

В протоколе доставки QoS2 получатель:

· ДОЛЖЕН ответить пакетом PUBREC, содежащим Packet Identifier из поступившего пакета PUBLISH, что подтверждает вступление во владение Application Message[MQTT-4.3.3-8].
· Если он отправил пакет PUBREC с Reason Code 0x80 или больше, то получатель ДОЛЖЕН обрабатывать любой последующий пакет PUBLISH, который содержит этот Packet Identifier, как новое Application Message[MQTT-4.3.3-9].
· Пока не будет принят соответствущий пакет PUBREL, получатель ДОЛЖЕН подтверждат любой последующий пакет PUBLISH с таким же Packet Identifier путем отправки PUBREC. Он НЕ ДОЛЖЕН в этом случае дублировать сообщения для любых дальнейших получателей[MQTT-4.3.3-10].
· ДОЛЖЕН отвечать пакетом PUBREL отправкой пакета PUBCOMP, который содержит такой же Packet Identifier, как и в пакете PUBREL[MQTT-4.3.3-11].
· После отправки PUBCOMP получатель ДОЛЖЕН обработать любой последующий пакет PUBLISH, который содержит такой Packet Identifier, как новое Application Message[MQTT-4.3.3-12].
· ДОЛЖЕН продолжить последовательность подтверждения QoS2, даже если применено истечение актуальности сообщения (message expiry)[MQTT-4.3.3-13].

4.4. Повторная доставка сообщения. Когда Клиент делает повторное подключение с Clean Start, установленным в 0, и присутствует сессия, и Клиент, и Сервер оба ДОЛЖНЫ повторно отправить любые не подтвержденные пакеты PUBLISH (у которых QoS > 0) и пакеты PUBREL, используя их оригинальные Packet Identifiers. Это единственное обстоятельство, когда Клиенту или Серверу ТРЕБУЕТСЯ повторно отправлять сообщения. Клиенты и Серверы НЕ ДОЛЖНЫ повторно отправлять сообщения в любое другое время[MQTT-4.4.0-1].

Если принятый PUBACK или PUBREC содержит Reason Code 0x80 или больше, то соответствующий пакет PUBLISH считается подвержденным, и НЕ ДОЛЖЕН передаваться повторно[MQTT-4.4.0-2].

Действие отправителя MQTT Control Packet Действие получателя
Сохранение сообщения    
Отправка PUBLISH QoS 2, DUP=0, < Packet Identifier > ---------- >  
    Сохранение < Packet Identifier >, затем инициирование дальнейшей доставки Application Message1(1)
    PUBREC < Packet Identifier >< Reason Code >
  < ----------  
Отбрасывание сообщения, сохранение принятого PUBREC < Packet Identifier >    
PUBREL < Packet Identifier >    
  ---------- >  
    Отбрасывание < Packet Identifier >
    Отправка PUBCOMP < Packet Identifier >
  < ----------  
Отбрасывание состояния сохранения    

Рис. 4.3. Пример диаграммы потока протокола QoS2.

Примечание (1): получателю не требуется завершать доставку Application Message перед отправкой PUBREC или PUBCOMP. Когда его оригинальный отправитель принимает пакет PUBREC, владение Application Message перемещается получателю. Однако получатель должен выполнить все проверки на наличие условий, которые могут привести сбою перенаправления (например превышение квоты, авторизация и т. п.) перед тем, как принять владение сообщением. Получатель показывает успех или сбой, используя подходящий Reason Code в PUBREC.

4.5. Получение сообщения. Когда Сервер принимает во владение поступившее Application Message, он ДОЛЖЕН добавить его в Session State для тех Клиентов, у которых имеются совпадающие подписки Subscriptions[MQTT-4.5.0-1]. Правила совпадения описаны в секции 4.7.

В нормальных условиях Клиенты получают сообщения в ответ на созданные ими подписки. Клиент также может получать сообщения, которые не соответствуют никакой из его явных подписок. Это может произойти, если Сервер автоматически назначает Клиенту подписку. Клиент также может получать сообщения, пока находится в процессе операция UNSUBSCRIBE. Клиент ДОЛЖЕН подтвержать любой пакет публикации, который получит, в соответствии с применимыми правилами QoS, независимо от того, выбирает ли он делать обработку Application Message, содержащегося в пакете[MQTT-4.5.0-2].

4.6. Порядок следования сообщений. Для Клиента применяются следующие правила, когда реализуется поток протокола, определенный в секции 4.3.

· Когда Клиент повторно посылает любые пакеты PUBLISH, он ДОЛЖЕН отправить их повторно в том же порядке, в каком были отправлены оригинальные пакеты PUBLISH (это применяется для сообщений QoS1 и QoS2)[MQTT-4.6.0-1].
· Клиент ДОЛЖЕН отправить пакеты PUBACK в том же порядке, в каком были приняты соответствующие пакеты PUBLISH (сообщения QoS1)[MQTT-4.6.0-2].
· Клиент ДОЛЖЕН послать пакеты PUBREC в том же порядке, в каком были приняты соответствующие пакеты PUBLISH (сообщения QoS2)[MQTT-4.6.0-3].
· Клиент ДОЛЖЕН послать пакеты PUBREL в том же порядке, в каком были приняты соответствующие пакеты PUBREC (сообщения QoS2)[MQTT-4.6.0-4].

Ordered Topic (упорядоченная тема) это тема, с которой Клиент может быть уверен, что Application Messages в этой теме от того же Клиента, при при этом получено такое же QoS в том же порядке, как сообщения были опубликованы. Когда Сервер обрабатывает сообщение, которое было опублликовано в Ordered Topic, он ДОЛЖЕН послать пакеты PUBLISH для потребителей (для тех же самых Topic и QoS) в том порядке, в котором они были получены от любого данного Клиента[MQTT-4.6.0-5]. Это дополннеие к правилам, перечисленным выше.

По умолчанию Сервер ДОЛЖЕН обрабатывать любую тему как Ordered Topic, когда он перенаправляет сообщения а не общих подписках (Non‑shared Subscriptions)[MQTT-4.6.0-6]. Сервер МОЖЕТ предоставить администрирование или другой механизм, чтобы позволить одну или большее количество тем не обрабатывать как Ordered Topic.

Замечания:

1. Перечисленные выше правила гарантируют, что когда поток сообщений публикуется и подписывается в Ordered Topic с QoS1, конечная копия каждого сообщения, полученного подписчиками, придет к ним в том же порядке, как были опубликованы сообщения. Если сообщение отправлено повторно, то дубликат сообщения может быть принят после одного из ранее принятых сообщений. Например, паблишер может послать сообщения в порядке 1, 2, 3, 4, однако подписчик может принять их в порядке 1, 2, 3, 2, 3, 4, если было отключение сети после отправки сообщения 3.

2. Если у обоих сторон, и у Клиента и Сервера установлен Receive Maximum в знаение 1, они следят за тем, чтобы в любой момент времени "в полете" находилось не более одного сообщения. В этом случае сообщение QoS1 не будет приниматься после любого последующего сообщения даже при повторном соединении. Например, подписчик может принять сообщения в порядке 1, 2, 3, 3, 4, но не в порядке 1, 2, 3, 2, 3, 4. Обратитесь к секции 4.9 Flow Control для подробностей, как используется Receive Maximum.

4.7. Topic Names и Topic Filters.

4.7.1. Topic wildcards. Для введения структуры в Topic Name используется разделитель уровня темы (topic level separator). Если он присутствует, то делит Topic Name на несколько "уровней тем".

Topic Filter подписки может содержать специальные wildcard-символы, которые позволяют Клиенту подисаться сразу на несколько тем.

В фильтрах темы (Topic Filter) могут использоваться символы wildcard, однако они НЕ ДОЛЖНЫ использоваться в Topic Name[MQTT-4.7.0-1].

4.7.1.1. Topic level separator. Прямой слеш ('/' U+002F) используется для разделения кадого уровня в дереве тем, и предоставления иерархической структуры для имен тем (Topic Name). Использование topic level separator имеет значение, когда в фильтрах тем, указанных подписывающимися Клиентами, встречается любой из двух wildcard-символов. Topic level separator-ы могут появляться в любом месте Topic Filter или Topic Name. Смежные topic level separator-s показывают уровень темы нулевой длины.

4.7.1.2. Multi-level wildcard. Символ номера ('#' U+0023) это wildcard-символ, который соотвествует любому количеству уровней в теме, т. е. многоуровневый wildcard. Многоуровневый wildcard представляет родителя и любое количество дочерних уровней. Символ многоуровневого wildcard ДОЛЖЕН быть указан либо на своем собственном, либо на следующем topic level separator. В любом случае он ДОЛЖЕН быть последним символом, указанным в Topic Filter[MQTT-4.7.1-1].

Замечание: например, если Клиент подписался на "sport/tennis/player1/#", то он будет получать сообщения, опубликованные с следущие Topic Names:

· "sport/tennis/player1".
· "sport/tennis/player1/ranking".
· "sport/tennis/player1/score/wimbledon".
· "sport/#" также соответствует одиночному "sport", поскольку # подключает родительский уровень.
· "#" допустим, и это приведет к приему каждого Application Message.
· "sport/tennis/#" допустим.
· "sport/tennis#" недопустим.
· "sport/tennis/#/ranking" недопустим.

4.7.1.3. Single-level wildcard. Символ плюса ('+' U+002B) это wildcard-символ, который соответствует только одному уровню темы (одноуровневый wildcard).

Одноуровневый wildcard может быть использован на любом уровне в Topic Filter, включая первый и последний уровни. Где он используется, он ДОЛЖЕН занимать весь уровень фильтра[MQTT-4.7.1-2]. Это может использоваться на более чем одном уровне в Topic Filter, и может использоваться совместно с многоуровневым wildcard.

Замечание: например, "sport/tennis/+" соответствует "sport/tennis/player1" и "sport/tennis/player2", но не "sport/tennis/player1/ranking". Также из-за того, что одноуровневый wildcard соответствует только одному уровню, "sport/+" не соответствует "sport", но соответствует "sport/".

· "+" допустим.
· "+/tennis/#" допустим.
· "sport+" недопустим.
· "sport/+/player1" допустим.
· "/finance" соответствует "+/+" и "/+", но не "+".

4.7.2. Темы, начинающиеся с $. Сервер НЕ ДОЛЖЕН сопоставлять фильтры тем (Topic Filter), начинающиеся на wildcard-символ (# или +) с именами тем, которые начинаются на символ $[MQTT-4.7.2-1]. Сервер ДОЛЖЕН (но это необязательно) предохранять Клиентов от использования таких Topic Name для обмена с другими Клиентами. Реализация Сервера МОЖЕТ использовать имена тем (Topic Name), которые начинаются с символа $, для других целей.

Замечания:

· $SYS/ широко адаптирован как префикс для тем, которые содержат специфичную для Сервера информацию или управляющее API.
· Приложения не могут использовать тему с начальным символом $ для своих собственных целей.
· Подписка на "#" не будет получать любые сообщения, опубликованные в тему, которые начинаются на $.
· Подписка на "+/monitor/Clients" не будет получать любые сообщения, опубликованные в "$SYS/monitor/Clients".
· Подписка на "$SYS/#" будет получать сообщения опубликованные в темы, начинающиеся с "$SYS/".
· Подписка на "$SYS/monitor/+" будет получать сообщения, опубликованные в "$SYS/monitor/Clients".
· Чтобы Клиент получал сообщения из тем, которые начинаются на $SYS/ и из тем, которые не начинаются на $, он должен подписаться и на "#", и на "$SYS/#".

4.7.3. Семантика тем и их использование. Следующие правила применяются к именам тем (Topic Name) и фильтрам тем (Topic Filter):

· Все имсена тем и фильтры тем ДОЛЖНЫ содержать как минимум 1 символ[MQTT-4.7.3-1].
· Имена тем и фильтры тем чувствительны к регистру символов (case sensitive).
· Имена тем и фильтры тем могут содежать в себе символы пробела.
· Начальный или завершающий символ '/' создает отдельное имя темы или отдельный фильтр темы.
· Допускается имя темы или фильтр темы, где содержится только один символ '/'.
· Имена тем и фильтры тем НЕ ДОЛЖНЫ включать null-символ (Unicode U+0000) [MQTT-4.7.3-2].
· Имена тем и фильтры тем это строки MQTT (UTF-8 Encoded Strings); они НЕ ДОЛЖНЫ кодировать больше чем 65535 байт[MQTT-4.7.3-3]. Подробнее про строки MQTT см. секцию 1.5.4.

Нет ограничений на количество уровней в Topic Name или Topic Filter, накладывается только ограничение на общую длину строки UTF-8 Encoded String.

При выполнении подписки соответствующий Сервер НЕ ДОЛЖЕН выполнять никакую нормализацию имен тем или фильтров тем, или любую модификацию или замену не распознанных символов[MQTT-4.7.3-4]. Каждый уровень в фильтре тем, не имеющий wildcard-символов, должен совпадать с соответствующим уровнем в имени темы, чтобы совпадение символа на этом уровне было успешным.

Замечание: правила кодирования UTF-8 означают, что сравнение фильтра темы и имени темы может быть выполнено либо путем сравнения кодирующих UTF-8 байт, либо путем сравнения символов Unicode.

· "ACCOUNTS" и "Accounts" это два разных имени темы.
· "Accounts payable" это допустимое имя темы.
· "/finance" отличается от "finance".

Application Message посылается в каждую подписку Клиента, когда фильтр подписки соответствует имени темы, содержащемуся в Application Message. Ресурс темы МОЖЕТ быть либо предварительно определен на Сервере администратором, либо МОЖЕТ быть создан Сервером динамически, когда он получит первую подписку или Application Message с таким именем темы. Сервер МОЖЕТ также использовать компонент безопасности для авторизации определенных действий на ресурсе темы для определенного Клиента.

4.8. Subscriptions. MQTT предоставляет 2 вида подиски (Subscription), Shared (общая подписка) и Non‑shared (не общая, или частная подписка).

Замечание: в ранних версиях MQTT все подписки были частные (Non‑shared).

4.8.1. Non‑shared Subscriptions. Частная подписка (Non‑shared Subscription) связана только с сессией MQTT Session, когда сессия создана. Каждая подписка включает фильтр темы (Topic Filter), который показывает, какие сообщения должны быть доставлены для этой сессии, и опции подписки (Subscription Options). Сервер отвечает за сбор сообщений, которые совпадают с фильтром тем, и передает их в сессии MQTT, когда активно сетевое соединение.

Сессия не может иметь больше одной частной подписки с одним и тем же фильтром темы, так что фильтр темы может использоваться как ключ для идентификации подписки в этой сессии.

Если существует несколько Клиентов, каждый из которых имеет свою собственную частную подписку на одну и ту же тему, то каждый Клиент получает свою собственную копию сообщений приложения (Application Messages), которые были опубликованы в такую тему. Это означает, что частные подписки не могут использоваться балансировки нагрузки Application Messages между несколькими потребляющими сообщения Клиентами, поскольку в таких случаях каждое сообщение доставляеться каждому подписавшемуся Клиенту.

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

Общие подписки идентифицируются с использованием специального стиля фильтра темы (Shared Subscription Topic Filter). Вот формат этого фильтра:

$share/{ShareName}/{filter}

· $share это литеральная строка, которая помечает фильтр темы как фильтр темы общей подписки.
· {ShareName} это символьная строка, которая не содержит символы '/', '+' или '#'.
· {filter} остаток строки, у которого тот же самый синтаксис, что и у фильтра темы частной подписки, см. секцию 4.7.

Фильтр темы общей подписки ДОЛЖЕН начинаться с $share/ и ДОЛЖЕН содержать ShareName, в котором присутствует как минимум 1 символ[MQTT-4.8.2-1]. Строка ShareName НЕ ДОЛЖНА содержать символы '/', '+' или '#', однако за ней ДОЛЖЕН идти символ '/'. За этим символом '/' ДОЛЖЕН идти фильтр темы (Topic Filter)[MQTT-4.8.2-2], как это описано в секции 4.7.

Замечание: общие подписки определены в области действия Сервера MQTT вместо области действия сессии MQTT. ShareName включено в фильтр темы общей подписки, так что на Сервере может быть несколько общих подписок с одним и тем же компонентом {filter}. Обычно приложения используют ShareName, чтобы представить группу сессий пописки, которые используют общую подписку.

Примеры:

· Общие подписки "$share/consumer1/sport/tennis/+" и "$share/consumer2/sport/tennis/+" это разные общие подписки, и таким образом они могут быть связаны с разными группами сессий. Они обе соответствуют тем же темам, что и частная подписка на sport/tennis/+ .

Если было бы опубликовано сообщение, которое совпало с sport/tennis/+ то его копия была бы отправлена точно одной из сессий, подисанных на $share/consumer1/sport/tennis/+ , отдельная копия сообщения была бы отправлена точно дной из сессий, подписанных на $share/consumer2/sport/tennis/+ и остальные копии были бы отправлены любым Клиентам с частной подпиской на sport/tennis/+ .

· Общая подписка "$share/consumer1//finance" совпадет с теми же темами, что и частная подписка на /finance.

Обратите внимание, что "$share/consumer1//finance" и "$share/consumer1/sport/tennis/+" это разные общие подписки, несмотря на то, что у них одинаковые ShareName. Хотя они могут быть связаны каким-либо образом, нет специфической взаимосвязи между ними, подразумевающей их одинаковые ShareName.

Общая подписка создается с использованием Shared Subscription Topic Filter в запросе SUBSCRIBE. Пока существует только одна сессия, подписанная на определенную общую подписку, эта общая подписка ведет себя так же, как и частная подписка, за исключением:

· Порции $share и {ShareName} фильтра темы не учитываются, когда происходит проверка на совпадение публикаций.
· При первой подписке в сессию не посылаются сохраненные сообщения (Retained Messages). Будут отправляться другие совпавшие с фильтром сообщения по мере их публикации.

Как только общая подписка появилась, могут появляться другие сессии для подписки с таким же Shared Subscription Topic Filter. Новая сессия связывается с общей подпиской как дополнительный подписчик. Retained messages не посылаются этому новому подписчику. Каждое последующее Application Message, которое совпало с общей подпиской, теперь будет отправляться только одной из сессий, которая подписалась на общую подписку.

Сессия может явно отключиться от общей подписки путем отправки пакета UNSUBSCRIBE, который содержит полный Shared Subscription Topic Filter. Сессии также отключаются от общей подписки, когда завершаются (не путайте завершение сессии с завершением сетевого соединения; сессия может распространяться на несколько сетевых соединений).

Общая подписка длится до тех пор, пока имеется хотя бы одна связанная с ней сессия (т. е. сессия, на которой был успешно выдан запрос SUBSCRIBE на её фильтр темы, и для которой не был завершен соответствующий запрос UNSUBSCRIBE). Общая подписка сохранится, когда завершится сессия, которая изначально создала эту общую подписку, пока существуют другие сессии, участвующие в этой общей подписке. Общая подписка завершится, и любые связанные с ней недоставленные сообщения будут удалены, когда не останется ни одной сессии, связанной с этой общей подпиской.

Замечания по общим подпискам:

· Если существует больше одной сессии, подписанных на общую подписку, то реализация Сервера свободна выбирать, основываясь на обработке сообщения за сообщением, какую сессию использовать для доставки, и какой критерий применяется для такого выбора.
· Разным подписавшимся Клиентам разрешается запрашивать различные уровни доставки (Requested QoS levels) в своих пакетах SUBSCRIBE. Сервер решает, какой Maximum QoS предоставить каждому Клиенту, и Серверу разрешается предоставлять разные уровни Maximum QoS отдельным подписчикам. Когда Application Message посылается Клиенту, Сервер ДОЛЖЕН руководствоваться предоставленным QoS для подписки Клиента[MQTT-4.8.2-3], так же как и при отправке сообщения подписчику.
· Если Сервер находится в процессе обработки отправки QoS2 сообщения выбранному подписавшемуся Клиенту, и соединение с этим Клиентом разорвалось до завершения отправки, то Сервер ДОЛЖЕН завершить доставку сообщения такому Клиенту, когда он подключится заново[MQTT-4.8.2-4], как это описано в секции 4.3.3. Если сессия Клиента завершится до его повторного подключения, то Сервер НЕ ДОЛЖЕН посылать это Application Message любому другому подписавшемуся Клиенту[MQTT-4.8.2-5].
· Если Сервер находится в процессе обработки отправки QoS1 сообщения выбранному подписавшемуся Клиенту, и соединение с этим Клиентом разорвалось до того, как Сервер получил подтверждение от Клиента, то Сервер МОЖЕТ подождать, когда этот Клиент подключится снова, и повторно передать ему сообщение. Если сессия Клиента завершится до того, как Клиент снова подключится, то Сервер МОЖЕТ отправить это Application Message другому Клиенту, который подписался на ту же самую общую подписку. Он МОЖЕТ попытаться передать сообщение другому Клиенту, как только потеряет соединение с первым Клиентом.
· Если Клиент ответит пакетом PUBACK или PUBREC, содержащим Reason Code 0x80 или больше, на пакет PUBLISH, полученный от Сервера, то Сервер ДОЛЖЕН отбросить Application Message и не пытаться отправить его любому другому подписчику[MQTT-4.8.2-6].
· Клиенту разрешено выдать второй запрос SUBSCRIBE в общую подписку на сессии, в которой он уже подписан эту общую подписку. Например, это может быть сделано для изменения запрашиваемого качества доставки (Requested QoS) для этой подписки, или по той причине, что у Клиента нет уверенности, что предыдущая подписка была завершена из-за того, что предыдущее сетевое соединение было закрыто. Такой второй запрос подписки не увеличит количество случаев, когда сеанс связан с общей подпиской, поэтому сессия оставит общую подписку на первом пакете UNSUBSCRIBE.
· Каждая общая подписка не зависит от любой другой. Возможно наличие двух общих подписок с перекрывающимися фильтрами. В таких случаях сообщение, которое совпадёт с обоими общими подписками, будет обработано отдельно для каждой из этих подписок. Если у Клиента есть общая подписка и частная подписка, и сообщение совпадёт с ними обоими, то Клиент получит копию сообщения из-за того, что имеет частную подписку. Вторая копия сообщения будет доставлена одному из участников общей подписки, и в результате этому же Клиенту может попасть вторая копия сообщения.

4.9. Flow Control (управление потоком). Клиенты и Серверы управляют количеством неподтвержденных пакетов PUBLISH, которые они получают, используя значение Receive Maximum, как это описано в секции 3.1.2.11.4 и секции 3.2.2.3.2. Receive Maximum устанавливает квоту отправки (send quota), используемую для ограничения количества пакетов PUBLISH с QOS > 0, которое может быть отправлено без приема PUBACK (для QoS1) или PUBCOMP (для QoS2). PUBACK и PUBCOMP пополняют квоту описанным ниже способом.

Клиент или Сервер ДОЛЖЕН установить свою начальную квоту отправки в ненулевое значение, не превышающее Receive Maximum[MQTT-4.9.0-1].

Каждый раз, когда Клиент или Сервер посылает пакет PUBLISH с QoS > 0, от декрементирует квоту отправки. Если квота отправки достигнет 0, то Клиент или Сервер НЕ ДОЛЖЕН посылать больше пакеты PUBLISH с QoS > 0[MQTT-4.9.0-2]. Он МОЖЕТ продолжать посылать пакеты PUBLISH с QoS0, или также МОЖЕТ выбрать приостановку их отправки. Клиент и Сервер ДОЛЖЕН продолжать обрабатывать все другие MQTT Control Packets и отвечать на них, даже если квота стала равна 0[MQTT-4.9.0-3].

Квота отправки инкрементируется на 1:

· Каждый раз, когда принят пакет PUBACK или PUBCOMP, независимо от того, переносит ли PUBACK или PUBCOMP код ошибки.
· Каждый раз, когда принят пакет PUBREC с Return Code 0x80 или больше.

Квота отправки не инкрементируется, если она уже достигла начального своего значения. Попытка инкремента свыше этого начального значения квоты может привести с повторной передаче пакета PUBREL после установки нового сетевого соединения.

См. секцию 3.3.4 для описания, как Клиенты и Серверы реагируют, если посылают больше пакетов PUBLISH, чем позволяет Receive Maximum.

Квота отправки и значение Receive Maximum не сохраняются между разными сетевыми соединениями, и заново инициализируются с каждым новым сетевым соединением, как это было описано выше. Они не составляют часть состояния сессии.

4.10. Request / Response. Некоторые приложения или стандарты могут захотеть запустить поверх MQTT взаимодействие типа запрос/ответ. Эта версия MQTT включает 3 свойства, которые могут быть задействованы для такой цели:

· Response Topic, описанный в секции 3.3.2.3.5.
· Correlation Data, описанные в секции 3.3.2.3.6.
· Request Response Information, описанная в секции 3.1.2.11.7.
· Response Information, описанная в секции 3.2.2.3.14.

Следующие ненормативные секции описывают, как могут использоваться эти свойства.

Клиент посылает сообщение запроса (Request Message) путем публикации Application Message, у которого установлена тема ответа (Response Topic), как это описано в секции 3.3.2.3.5. Запрос может включать в себе свойство Correlation Data, это описано в секции 3.3.2.3.6.

4.10.1. Basic Request Response (базовый алгоритм запроса на ответ, ненормативный пример). Взаимодействие Request/Response проходит следующим образом:

1. Клиент MQTT (запрашивающий, Requester) публикует Request Message в определенную тему. Request Message это Application Message с Response Topic.

2. Другой Клиент MQTT (отвечающий на запрос, Responder) должен быть подписан на Topic Filter, который совпадает с Topic Name, использовавшемуся при публикации Request Message. В результате он получит Request Message. Могут быть несколько Responder-ов, подписанных на это Topic Name, или может быть ни одного.

3. Responder предпринимает подходящее действие, основываясь на Request Message, и затем публикует Response Message в Topic Name, которое было указано в свойстве Response Topic, переданном в Request Message.

4. При типовом использовании Requester подписывается на Response Topic и таким образом получает Response Message. Однако некоторые другие Клиенты могут быть подписаны на Response Topic, в таком случае Response Message будет также принято и обработано таким Клиентом. Как и в случае с Request Message, на тему, в которую отправляется Response Message, может быть подписано несколько Клиентов, или ни одного.

Если Request Message содержит свойство Correlation Data, то Responder копирует это свойство в Response Message, и это может использоваться получателем Response Message для ассоциации с оригинальным запросом. Response Message не включает свойство Response Topic.

Сервер MQTT перенаправляет тему ответа (Response Topic) и свойство Correlation Data в сообщении запроса (Request Message), и Correlation Data в сообщении ответа (Response Message). Сервер обрабатывает Request Message и Response Message так же, как и любые другие Application Message.

Requester нормально подписывается на Response Topic перед публикацией Request Message. Если нет подписчиков на Response Topic, когда было отправлено Response Message, то Response Message не будет доставлено никому из Клиентов.

Request Message и Response Message может быть любого уровня качества доставки (QoS), и Responder может использовать сессию с ненулевым временем жизни (Session Expiry Interval). Обычная практика отправить Request Messages с QoS0, только когда Responder считается подключенным, но это необязательно.

Responder может использовать Shared Subscription, чтобы иметь возможность опрашивать отвечающих Клиентов. Однако имейте в виду, что когда используются общие подписки, нет гарантии что сообщение будет доставлено, когда имеется несколько Клиентов на общей подписке.

В зоне ответственность Requester-а обеспечить необходимую авторизацию для публикаци в тему запроса, и для подписки на имя темы (Topic Name), которая устанавливается в свойстве темы ответа (Response Topic). В зоне ответственности Responder-а обеспечить авторизацию в подписку на тему запроса (Request Topic) и публикацию в тему ответа (Response Topic). Хотя авторизация тем выходит за рамки описания этого стандарта, рекомендуется для Серверов реализовать такую авторизацию.

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

Чтобы помочь с этой проблемой, эта спецификация определяет свойство в пакете CONNACK, которое называется Response Information. Сервер может использовать это свойство, чтобы направить Клиента в его выборе используемого Response Topic. Этот механизм опционален как для Клиента, так и для Сервера. В момент коннекта Клиент запрашивает, чтобы Сервер послал Response Information путем установки свойства Request Response Information в пакете CONNECT. Это приведет к тому, что Сервер вставит свойство Response Information (строку UTF-8 Encoded String) для отправки в пакете CONNACK.

Эта спецификация не определяет содержимое Response Information, но может использоваться для передачи глобально уникальной порции дерева тем, которая зарезервирована для этого Клиента как минимум в течение времени жизни его сессии. Использование этого механизма позволяет выполнить конфигурацию однократно на Сервере вместо того, чтобы делать это на каждом Клиенте.

См. секцию 3.1.2.11.7 для определения информации ответа (Response Information).

4.11. Перенаправление Сервера (Server redirection). Сервер может запросить, чтобы Клиент использовал другой Сервер, путем отправки CONNACK или DISCONNECT с Reason Codes 0x9C (Use another server), или 0x9D (Server moved), как описано в секции 4.13. Когда посылается один из таких кодов ответа (Reason Codes), Сервер МОЖЕТ также подключить свойство Server Reference, чтобы показать местонахождение Сервера или Серверов, которые Клиент МОГ БЫ использовать.

Reason Code 0x9C (Use another server) указывает, что Клиент ДОЛЖЕН БЫ временно переключиться на использование другого Сервера. Другой Сервер может быть либо уже известен Клиенту, либо указан Сервером в свойстве Server Reference пакета CONNACK или DISCONNECT.

Reason Code 0x9D (Server moved) указывает, что Клиенту СЛЕДУЕТ постоянно переключиться на использование другого Сервера. Другой Сервер либо уже известен Клиенту, либо указан Сервером в свойстве Server Reference пакета CONNACK или DISCONNECT.

Server Reference это строка MQTT (UTF-8 Encoded String). Значение этой строки представляет список ссылок на Серверы (их адресов) с разделителем символом пробела. Формат ссылок не определяется этой спецификацией.

Замечания:

1. Рекомендуется, чтобы каждая ссылка на Сервер стояла из имени, за которой опционально идет двоеточие и номер порта. Если имя содержит двоеточие, то строка имени может быть заключено в квадратные скобки('[' и ']'). Имя, заключенное в квадратные скобки, не может содержать в себе символ правой квадратной скобки (']'). Это используется для представления литерального адреса IPv6, который использует для разделителей двоеточие. Это упрощает версию авторизации URI, как описано в [RFC3986].

2. Ссылка в Server Reference обычно представляет имя хоста (host name), имя DNS [RFC1035], имя SRV [RFC2782], либо литеральный IP-адрес. Перед именем хоста указывается обозначение протокола (mqtt://). Значение, которое идет за именем хоста и разделителем в виде символа двоеточия, обычно означает десятичное значение номера порта. Это не требуется, когда информация об используемом порте предоставляется службой разрешения имен (такой как SRV), или когда используется порт по умолчанию.

3. Если указывается несколько ссылок, то ожидается, что Клиент выберет одну из них.

4. Примеры Server Reference:

myserver.xyz.org
myserver.xyz.org:8883
10.10.151.22:8883 [fe80::9610:3eff:fe1c]:1883

Примечание: некоторые библиотеки требуют указать перед именем хоста обозначение протокола, например mqtt://10.10.151.22:8883.

Серверу разрешено никогда не отправлять Server Reference, а Клиенту разрешено игнорировать Server Reference. Эта функция может использоваться для балансировки нагрузки на Серверы, для перемещения Сервера, и для позиционирования Клиента по отношению к Серверу.

4.12. Enhanced authentication (расширенная аутентификация). MQTT-пакет CONNECT поддерживает базовую аутентификацию сетевого соединения, используя поля User Name и Password. Хотя эти поля назначены для простой аутентификации паролем, они могут быть использованы для других форм аутентификации, таких как передача токена в качестве Password.

Расширенная аутентификация дополняет базовую добавлением аутентификации стиля challenge / response. Это может вовлечь обмен пакетами AUTH между Клиентом и Сервером после пакета CONNECT и перед пакетом CONNACK.

Чтобы начать расширенную аутентификацию, Клиент подключает Authentication Method в пакет CONNECT. Это указывает используемый метод аутентификации. Если Сервер не поддерживает Authentication Method, предоставленный Клиентом, то Сервер МОЖЕТ послать CONNACK с Reason Code 0x8C (Bad authentication method) или 0x87 (Not Authorized), как это описано в секции 4.13, и ДОЛЖЕН закрыть сетевое соединение[MQTT-4.12.0-1].

Authentication Method это соглашение между Клиентом и Сервером о значении и смысле данных, посылаемых в полях Authentication Data и любых других полях пакета CONNECT, и соглашение об обработке, необходимой для выполнения Клиентом и Сервером, чтобы завершить аутентификацию.

Замечание: Authentication Method обычно это механизм SASL, и использование такого зарегистрированного имени способствует успешному обмену. Однако Authentication Method не ограничен использованием зарегистрированных механизмов SASL.

Если Authentication Method, выбранный Клиентом, указывает, что первым данные посылает Клиент, то ожидается, что Клиент ДОЛЖЕН подключить свойство Authentication Data в пакете CONNECT. Это свойство может использоваться для предоставления данных, как это указано полем метода аутентификации (Authentication Method). Содержимое Authentication Data определяется методом аутентификации.

Если Серверу нужна дополнительная информация, чтобы завершить аутентификацию, то он может послать Клиенту пакет AUTH. Этот пакет ДОЛЖЕН содержать Reason Code 0x18 (Continue authentication)[MQTT-4.12.0-2]. Если метод аутентификации требует, чтобы Сервер посылал данные аутентификации Клиенту, то Сервер посылает их в поле Authentication Data.

Клиент отвечает на пакет AUTH, полученный от Сервера, путем отправки другого пакета AUTH. Этот пакет ДОЛЖЕН содержать Reason Code 0x18 (Continue authentication)[MQTT-4.12.0-3]. Если метод аутентификации требует, чтобы Клиент посылал данные аутентификации Серверу, то Клиент посылает их в поле Authentication Data.

Клиент и Сервер обмениваются пакетами AUTH, как это необходимо, пока Сервер не примет аутентификацию путем отправки пакета CONNACK с Reason Code 0. Если подтверждение аутентификации требует данных, отправляемых Клиенту, то они посылаются в поле Authentication Data.

Клиент может закрыть соединение в любой момент этого процесса. Он МОЖЕТ перед этим послать пакет DISCONNECT. Сервер может отклонить аутентификацию в любой момент этого процесс. Он МОЖЕТ послать пакет CONNACK с Reason Code 0x80 или больше, как это описано в секции 4.13, и ДОЛЖЕН закрыть сетевое соединение[MQTT-4.12.0-4].

Если в начальном пакете CONNECT подключено свойство Authentication Method, то все пакеты AUTH, и любой пакет успешной авторизации CONNACK ДОЛЖЕН включать свойство Authentication Method с таким же значением, какое было в пакете CONNECT[MQTT-4.12.0-5].

Реализация расширенной аутентификации ОПЦИОНАЛЬНА как для Клиента, так и для Сервера. Если Клиент не включает Authentication Method в CONNECT, то Сервер НЕ ДОЛЖЕН посылать пакет AUTH, и НЕ ДОЛЖЕН посылать Authentication Method в пакете CONNACK[MQTT-4.12.0-6]. Если Клиент не подключил Authentication Method в пакет CONNECT, то Клиент НЕ ДОЛЖЕН посылать пакет AUTH Серверу[MQTT-4.12.0-7].

Если Клиент не подключает Authentication Method в пакет CONNECT, то Сервер возможно ДОЛЖЕН аутентифицировать Клиента, используя некоторую часть или всю информацию пакета CONNECT, сессии TLS и сетевого соединения.

Ненормативный пример, показывающий вызов SCRAM:

· Client -> Server: CONNECT Authentication Method="SCRAM-SHA-1" Authentication Data=client-first-data
· Server -> Client: AUTH rc=0x18 Authentication Method="SCRAM-SHA-1" Authentication Data=server-first-data
· Client -> Server: AUTH rc=0x18 Authentication Method="SCRAM-SHA-1" Authentication Data=client-final-data
· Server -> Client: CONNACK rc=0 Authentication Method="SCRAM-SHA-1" Authentication Data=server-final-data

Ненормативный пример, показывающий вызов Kerberos^

· Client -> Server: CONNECT Authentication Method="GS2-KRB5"
· Server -> Client: AUTH rc=0x18 Authentication Method="GS2-KRB5"
· Client -> Server: AUTH rc=0x18 Authentication Method="GS2-KRB5" Authentication Data=initial context token
· Server -> Client: AUTH rc=0x18 Authentication Method="GS2-KRB5" Authentication Data=reply context token
· Client -> Server: AUTH rc=0x18 Authentication Method="GS2-KRB5"
· Server -> Client: CONNACK rc=0 Authentication Method="GS2-KRB5" Authentication Data=outcome of authentication

4.12.1. Повторная аутентификация. Если Клиент предоставил Authentication Method в пакете CONNECT, то он может инициировать повторную аутентификацию в любой момент после получения CONNACK. Он делает это отправкой пакета AUTH с Reason Code 0x19 (Re-authentication). Клиент ДОЛЖЕН установить Authentication Method в такое же значение, как Authentication Method, изначально используемый для аутентификации сетевого соединения[MQTT-4.12.1-1]. Если метод аутентификации требует, чтобы сначала были данные от Клиента, то этот пакет AUTH содержит первую часть данных аутентификации в поле Authentication Data.

Сервер отвечает на этот запрос повторной аутентификации отправкой пакета AUTH Клиенту с Reason Code 0x00 (Success), чтобы показать, что повторная аутентификация завершена, или Reason Code 0x18 (Continue authentication), чтобы показать, что нужны еще данные аутентификации. Клиент может ответить дополнительными данными аутентификации отправкой пакета AUTH с Reason Code 0x18 (Continue authentication). Этот поток обмена продолжается с оригинальным методом аутентификации, пока повторная аутентификация не завершится успешно или неудачно.

Если повторная аутентификация завершилась неудачно, то Клиент или Сервер ДОЛЖЕН послать DISCONNECT с подходящим Reason Code, как это описано в секции 4.13, и ДОЛЖЕН закрыть сетевое соединение[MQTT-4.12.1-2].

Во время этой последовательности повторной аутентификации поток обмена другими пакетами между Клиентом и Сервером может продолжаться с использованием предыдущей аутентификации.

Замечание: Сервер может ограничить область изменений, которые Клиент может попытаться ввести в повторной аутентификации, путем отклонения повторной аутентификации. Например, если Сервер не позволяет поменять User Name, то он может оборвать любую попытку повторной аутентификации, которая меняет User Name.

4.13. Handling errors (обработка ошибок).

4.13.1. Malformed Packet и Protocol Errors. Определения Malformed Packet и Protocol Errors содержатся в секции 1.2, посвященной терминологии, и некоторые, но не все случаи ошибок, описаны в этой спецификации. Строгость, с которой Клиент или Сервер проверяют полученный MQTT Control Packet, будет компромиссом между:

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

Если отправитель совместим с этой спецификацией, то он не будет отправлять неправильно сформированные пакеты (Malformed Packets) или предпринимать действия, вызывающие ошибки протокола (Protocol Errors). Однако, если Клиент посылает пакеты управления (MQTT Control Packet) перед тем, как получит CONNACK, это может привести к Protocol Error из-за неправильного предположения о возможностях Сервера. См. секцию 3.1.4 CONNECT Actions.

Значения Reason Codes, используемые для Malformed Packet и Protocol Error:

0x81           Malformed Packet
0x82           Protocol Error
0x93           Receive Maximum exceeded
0x95           Packet too large
0x9A           Retain not supported
0x9B           QoS not supported
0x9E           Shared Subscriptions not supported
0xA1           Subscription Identifiers not supported
0xA2           Wildcard Subscriptions not supported

Когда Клиент детектировал Malformed Packet или Protocol Error, и Reason Code, предоставленный в этой спецификации, то он возможно ДОЛЖЕН закрыть сетевое соединение. В случае ошибки в пакете AUTH он МОЖЕТ послать пакет DISCONNECT, содержащий код причины (reason code) перед тем, как закроет сетевое соединение. В случае ошибки в любом другом пакете он возможно ДОЛЖЕН послать пакет DISCONNECT, содержащий reason code перед закрытием сетевого соединения. При этом используется Reason Code 0x81 (Malformed Packet) или 0x82 (Protocol Error), если для этого случая не предусмотрено более специфичного Reason Code, как определено в секции 3.14.2.1 Disconnect Reason Code.

Когда Сервер детектировал Malformed Packet или Protocol Error, и Reason Code, предоставленный в этой спецификации, он ДОЛЖЕН закрыть сетевое соединение[MQTT-4.13.1-1]. В случае ошибки в пакете CONNECT он МОЖЕТ послать пакет CONNACK, содержащий Reason Code, перед закрытием сетевого соединения. В случае ошибки в любом другом пакете он возможно ДОЛЖЕН послать пакет DISCONNECT, содержащий Reason Code, перед закрытием сетевого соединения. Используется Reason Code 0x81 (Malformed Packet) или 0x82 (Protocol Error), если не походит более специфичный Reason Code, как определено в секции 3.2.2.2 - Connect Reason Code или в секции 3.14.2.1 – Disconnect Reason Code. Для любых других сессий никаких последствий нет.

Если либо Сервер, либо Клиент опустит проверку некоторой функции MQTT Control Packet, он может не обнаружить ошибку, и как следствие может пропустить поврежденные данные.

4.13.2. Другие ошибки. Ошибки, отличающиеся от Malformed Packet и Protocol Errors, не могут ожидаться отправителем, поскольку у получателя могут быть ограничения, которые он не передал отправителю. Принимающий Клиент или север может столкнуться со случайной ошибкой, такой как нехватка памяти, что не даст провести успешную обработку отдельного MQTT Control Packet.

Пакеты подтверждения PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK с Reason Code 0x80 или больше показывают, что принятый пакет, идентифицированный значением Packet Identifier, был ошибочным. Здесь нет никаких последствий для других сессий или обработки других пакетов в одной и той же сессии.

Пакеты CONNACK и DISCONNECT позволяют Reason Code 0x80 или больше показывать, что сетевое соединение будет закрыто. Если указан Reason Code 0x80 или больше, то сетевое соединение ДОЛЖНО быть закрыто, независимо от того, какой пакет отправлен, CONNACK или DISCONNECT[MQTT-4.13.2-1]. Отправка одного из этих Reason Codes не имеет последствие для какой-либо другой сессии.

Если MQTT Control Packet содержит несколько ошибок, то получатель пакета может проверить пакет в любом порядке, и предпринять подходящее действие для любой из найденных ошибок.

См. секцию 5.4.9 for information about handling Disallowed Unicode code points.

[5. Security (ненормативная информация)]

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

Реализациям MQTT, скорее всего, придется идти в ногу с развитием стандартов сред безопасности.

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

Строго рекомендуется, чтобы реализации Сервера, которые предоставляют TLS [RFC5246], должны использовать TCP порт 8883 (IANA service name: secure-mqtt).

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

· Устройства могут быть скомпрометированы.
· Данные в состоянии покоя на Клиентах и Серверах, могут быть доступны для несанкционированного доступа.
· Поведение протокола может иметь побочные эффекты (например "timing attacks").
· Атаки на отказ в обслуживании (Denial of Service, DoS).
· Коммуникации могут быть перехвачены, подменены, перенаправлены или раскрыты.
· Инжекция поддельных MQTT Control Packet.

Решения MQTT часто разворачиваются во потенциально враждебных средах обмена данными. В таких случаях реализациям часто потребуются механизмы для:

· Аутентификации пользователей и устройств.
· Авторизации для доступа к ресурсам Сервера.
· Проверки целостности MQTT Control Packets и содержащихся в них данных приложения.
· Приватности MQTT Control Packets и содержащихся в них данных приложения.

В дополнение к проблемам технической безопасности могут быть также географические (например U.S.-EU Privacy Shield Framework [USEUPRIVSH]), специфические для индустрии (например PCI DSS [PCIDSS]) и регуляторные требования (например Sarbanes-Oxley [SARBANES]).

5.2. Решения MQTT: безопасность и сертификация. Реализация может захотеть предоставить совместимость с определенными индустриальными стандартами безопасности, такими как NIST Cyber Security Framework [NISTCSF], PCI-DSS [PCIDSS]), FIPS-140-2 [FIPS1402] и NSA Suite B [NSAB].

Руководство по использованию MQTT в NIST Cyber Security Framework [NISTCSF] можно найти в дополнительной публикации MQTT "MQTT and the NIST Framework for Improving Critical Infrastructure Cybersecurity" [MQTTNIST]. Использование надежных, проверенных индустрией и сертифицированных технологий поможет удовлетворению требований совместимости.

5.3. Облегченная криптография и устройства с ограниченными ресурсами. Advanced Encryption Standard [AES] является наиболее широко используемым алгоритмом шифрования. Существует аппаратная поддержка AES на многих процессорах, но не всех популярных микроконтроллерах. Алгоритм шифрования ChaCha20 [CHACHA20] шифрует и расшифровывает данные программно быстрее всего, но он не так широко доступен, как AES.

ISO 29192 [ISO29192] предоставляет рекомендации для криптографических примитивов, специально учитывающих ограничения "low end" устройств.

5.4. Замечания по реализации. При реализации или использовании MQTT следует учитывать множество проблем безопасности. Описание в следующей секции не должны рассматриваться как обязательные, т. е. как "check list".

Реализация может захотеть достичь некоторых, или всех, следующих функций:

5.4.1. Аутентификация Клиентов Сервером. Пакет CONNECT содержит поля User Name и Password. Реализации могут выбрать, как использовать содержимое этих полей. Реализации могут предоставить собственный механизм аутентификации, использовать внешнюю систему аутентификации, такую как токены LDAP [RFC4511] или OAuth [RFC6749], или использование механизма аутентификации операционной системы.

MQTT v5.0 предоставляет механизм расширенной аутентификации, как это описано в секции 4.12. Это требует поддержки как со стороны Клиента, так и Сервера.

Реализации, которые передают данные аутентификации в виде простого текста, либо с применением обфускации таких элементов данных, или вовсе не требующие данных аутентификации, должны иметь в виду, что имеется риск успешной атаки типа "человек посередине" (Man-in-the-Middle attack) и записи и проигрывания пакета (replay attack). Секция 5.4.5 показывает способы обеспечения приватности данных.

Virtual Private Network (VPN) между Клиентами и Серверами может предоставить конфиденциальность таких данных, и обеспечить их прием только от авторизованных Клиентов.

Когда используется TLS [RFC5246], отправленные от Клиента сертификаты TLS могут использоваться Сервером для аутентификации Клиента.

Реализации могут позволять аутентификацию, когда учетные данные посылаются в Application Message от Клиента к Серверу.

5.4.2. Авторизация Клиентов Сервером. Если Клиент успешно аутентифицирован, реализация Сервера должна проверять, авторизован ли Клиент, прежде чем принимать его подключение.

Авторизация может быть основана на информации, предоставленной Клиентом, такой как User Name, hostname/IP адрес Клиента, или происходить из результата механизмов аутентификации.

В частности, реализация должна проверять, что Клиент авторизован для использования Client Identifier, поскольку это дает доступ к MQTT Session State (описано в секции 4.1). Эта проверка авторизации предоставляет защиту для случаев, когда Клиент, случайно или злонамеренно, предоставляет Client Identifier, который уже используется каким-то другим Клиентом.

Реализация должна предоставлять управление доступом, которое происходит после CONNECT, чтобы ограничить возможность Клиентов публикации в определенные темы (Topics) или подписки с использованием определенных фильтров тем (Topic Filters). Реализация должна рассмотреть ограничение доступа к Topic Filters, у которых широкая область действия, такой как фильтр темы #.

5.4.3. Аутентификация Сервера Клиентом. Протокол MQTT не применяет симметричное доверие. При использовании базовой аутентификации нет механизма аутентификации Клиентом Сервера. Некоторые виды расширенной аутентификации допускают взаимную аутентификацию сторон обмена.

При использовании [RFC5246], для аутентификации Сервера Клиентом могут использоваться сертификаты TLS, отправляемые Сервером. Реализации, предоставляющие службу MQTT для нескольких имен хостов по одному IP-адресу, должны знать о расширении Server Name Indication для TLS, которое определено в секции 3 [RFC6066]. Это позволит Клиенту указать имя хоста Сервера, к которому о пытается подключиться.

Реализация может разрешить аутентификацию, когда учетные данные передаются в Application Message от Сервера Клиенту. MQTT v5.0 предоставляет механизм расширенной аутентификации, как это описано в секции 4.12, который может использоваться для аутентификации Сервера Клиентом. Чтобы это использовать, требуется поддержка как со стороны Клиента, так и Сервера.

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

5.4.4. Целостность сообщений и пакетов управления. Приложения могут независимо подключать значения хэша в своих сообщениях (Application Messages). Это может предоставить проверку целостности содержимого пакетов публикации, когда они передаются по сети, и в состоянии покоя.

TLS [RFC5246] предоставляет алгоритмы хэша для проверки целостности данных, пересылаемых по сети.

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

5.4.5. Приватность сообщений и пакетов управления. TLS [RFC5246] может предоставить шифрование данных, посылаемых через сеть. Существуют допустимые наборы шифров TLS, которые включают NULL-алгоритм шифрования, который не шифрует данные. Для обеспечения приватности Клиентов и Серверов следует избегать таких шифров.

Приложение может независимо шифровать содержимое своих Application Messages. Это может обеспечить приватность Application Message как при передаче по сети, так и в состоянии покоя. Однако это не обеспечит приватность других свойств Application Message, таких как Topic Name.

Реализации Клиента и Сервера могут предоставить зашифрованное хранилище для данных в состоянии покоя, таких как Application Messages, сохраненных как часть сессии.

Использование VPN для соединения между Клиентами и Серверами может предоставить приватность данных в секции сети, которая покрыта трафиком VPN.

5.4.6. Безотказная передача сообщения. Разработчикам приложения может потребоваться рассмотреть подходящие стратегии, чтобы достичь безотказной доставки от точки до точки.

5.4.7. Обнаружение компрометации Клиентов и Серверов. Реализации Клиента и Сервера, использующие TLS [RFC5246], должны предоставить возможности для гарантии, что любые сертификаты TLS, предоставленные при инициации соединения TLS, ассоциированы с именем подключающегося Клиента, или Сервера, к которому происходит подключение.

Реализации Клиента и Сервера, использующие TLS, могут выбрать предоставление возможностей проверки списков отозванных сертификатов (Certificate Revocation Lists, CRL [RFC5280]) и Online Certificate Status Protocol (OSCP) [RFC6960], чтобы предотвратить использование отозванных сертификатов.

Физические развертывания могут комбинировать защищенное от взлома оборудование с передачей определенных данных в Application Messages. Например, измеритель может иметь на борту встроенный приемник GPS для гарантии, что решение не используется в неавторизованной локации. [IEEE8021AR] это стандарт реализации аутентификации идентичности устройств с использованием криптографически связанного идентификатора.

5.4.8. Детектирование ненормального поведения. Реализации Сервера могут отслеживать поведение Клиента, чтобы обнаружить потенциальные инциденты безопасности. Например:

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

Реализации Сервера могут закрыть сетевое соединение Клиентов, нарушающих правила безопасности.

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

Развертывания могут использовать контроль на уровне сети (где это возможно) для реализации ограничения частоты запросов или блокировок, основываясь на IP-адресе или другой информации.

5.4.9. Обработка запрещенных кодовых точек Unicode. Секция 1.5.4 описывает запрещенные коды, которые не должны использоваться в UTF-8 Encoded String. Реализация Клиента или Сервера может выбрать проверку этих кодов, что они не используются в строках MQTT, таких как Topic Name или Properties.

Если Сервер не проверяет коды в UTF-8 Encoded String, однако подписавшийся Клиент проверяет, то второй Клиент может привести к тому, что подписавшийся Клиент закроет сетевое соединение путем публикации Topic Name или использования Properties, где содержится Disallowed Unicode code point. В этой секции даются рекомендованные шаги, которые можно предпринять для предотвращения этой проблемы.

Подобная проблема может возникнуть, когда Клиент проверяет полезную нагрузку на соответствие Payload Format Indicator, а Сервер этого не делает. Соображения и средства защиты от этого подобны тем, что используются для обработки Disallowed Unicode code points.

5.4.9.1. Замечания для использования Disallowed Unicode code points. Реализация, которая нормально выбирает использование проверки корректности UTF-8 Encoded strings, и она проверяет, что запрещенные коды (Disallowed Unicode code points) никогда не используются. Это позволяет избежать сложностей реализации, таких как использование библиотек, чувствительных к этим кодам, и также защищает приложения от их обработки.

Проверка, что запрещенные коды не используются, устраняет некоторые проблемы безопасности. Существуют эксплойты безопасности, использующие символы управления в файлах лога для маскировки записей, или запутывания инструментария, который обрабатывает файлы этих логов. Unicode Noncharacters обычно используются как специальные маркеры, и разрешение их в UTF-8 Encoded Strings могут разрешить работу таких эксплойтов.

5.4.9.2. Взаимодействие между публикаторами и подписчиками. Публикатор Application Message обычно ожидает, что Сервер перенаправит это сообщение подписчикам, и что эти подписчики смогут обработать сообщения.

Существуют некоторые условия, в которых публикация Клиента может привести к тому, что заставит подписавшийся Клиент закрыть сетевое соединение. Рассмотрим ситуацию, где:

· Клиент публикует Application Message, используя Topic Name, содержащее один из запрещенных кодов (Disallowed Unicode code points).

· Библиотека публикующего Клиента позволяет использовать запрещенные коды для Topic Name вместо того, что бы их отбрасывать.

· Публикующий Клиент авторизован для отправки публикации.

· Подписывающийся Клиент авторизован для использования Topic Filter, который совпадает с Topic Name. Обратите внимание, что Disallowed Unicode code point может появиться в части Topic Name, попадающей под wildcard-символ в Topic Filter.

· Сервер перенаправляет сообщение совпавшему подписчику вместо того, чтобы отключить публикатора.

· В этом случае подписавшийся Клиент может:

    - Закрыть сетевое соединение из-за того, что он не позволяет использовать Disallowed Unicode code points, возможно перед этим отправив DISCONNECT. Для сообщений QoS1 и QoS2 это может привести к тому, что Сервер пошлет сообщение снова, что снова заставит Клиента закрыть сетевое соединение.
    - Отклонить Application Message отправкой кода Reason Code больше или равного 0x80, в пакете PUBACK (QoS1) или PUBREC (QoS2).
    - Принять Application Message, но не обрабатывать его, потому что оно содержит Disallowed Unicode code points.
    - Успешно обработать Application Message.

Возможность для Клиента закрыть сетевое соединение может остаться незамеченной до тех пор, пока публикатор использует один из Disallowed Unicode code points.

5.4.9.3. Исправления. Если существует возможность, что Disallowed Unicode code point может быть включена в Topic Name или другое свойство для Клиента, то владелец решения может принять одно из следующих предложений:

1) Поменять реализацию Сервера, чтобы она отклоняла строки MQTT (UTF-8 Encoded Strings), содержащие Disallowed Unicode code point, либо отправкой Reason Code, больше или равного 0x80, либо закрытием сетевого соединения.
2) Поменять библиотеку Клиента, используемую подписчиками на такую, которая будет толерантной для Disallowed Code points. Клиент может либо обработать, либо отбросить сообщения с UTF-8 Encoded Strings, которые содержат Disallowed Unicode code points, пока он продолжает обрабатывать протокол.

5.4.10. Другие соображения по безопасности. Если сертификаты TLS Клиента ли Сервера потеряны, или считается, что они могут быть скомпрометированными, то они должны быть отозваны (утилизированы списками CRL [RFC5280] и/или OSCP [RFC6960]).

Учетные данные Клиента или Сервера, такие как User Name и Password, которые потеряны или считаются скомпрометированными, должны быть отозваны или назначены заново.

В случае длительных соединений:

· Реализации Клиента и Сервера, использующие TLS [RFC5246], должны позволять повторной установке сессии устанавливать новые параметры криптографии (заменять ключи сессии, менять учетные данные аутентификации).
· Серверы могут закрыть сетевое соединение Клиента и потребовать от него повторной аутентификации с новыми учетными данными.
· Серверы могут требовать от своих Клиентов периодически проходить аутентификацию заново с использованием механизма, описанного в секции 4.12.1.

Ограниченные устройства и Клиенты в ограниченных сетях могут использовать возобновление сеанса TLS [RFC5246], чтобы снизить затраты на повторное подключение сеансов TLS [RFC5246].

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

5.4.11. Использование SOCKS. Реализация Клиентов должна быть осведомлена о том, что некоторые рабочие окружения будут требовать использования SOCKSv5 [RFC1928] proxy, чтобы выполнить исходящие сетевые соединения. Некоторые реализации MQTT могут использовать альтернативные защищенные туннели (например SSH) посредством использования SOCKS. Там, где реализации выбирают использование SOCKS, они должны поддерживать для SOCKS proxy и anonymous-аутентификацию, и аутентификацию через User Name и Password. В последнем случае реализации должны быть осведомлены о том, что аутентификация SOCKS может происходить открытым текстом, так что следует избегать использования тех же самых учетных данных для подключения к Серверу MQTT.

5.4.12. Профили безопасности. Реализаторы и разработчики решения могут рассмотреть безопасность как набор профилей, которые могут быть применены к протоколу MQTT. Ниже приведен пример многоуровневой иерархии безопасности.

5.4.12.1. Открытый профиль коммуникации (clear communication profile). Когда используется clear communication profile, протокол MQTT работает поверх открытой сети без дополнительных механизмов защищенной связи.

5.4.12.2. Защищенный сетевой профиль коммуникаций (secured network communication profile). Когда используется secured network communication profile, протокол MQTT работает поверх физической или виртуальной сети, которая содержит средства управления безопасностью, например VPN или физически защищенная сеть.

5.4.12.3. Защищенный транспортный профиль (secured transport profile). Когда используется secured transport profile, протокол MQTT protocol работает поверх физической или виртуальной сети и использует TLS [RFC5246], что предоставляет аутентификацию, проверку целостности данных и их конфиденциальность.

Может использоваться аутентификация Клиента TLS [RFC5246] в дополнение - или вместо - аутентификации Клиента MQTT в соответствии с полями User Name и Password.

5.4.12.4. Индустриальные профили безопасности. Предполагается, что протокол MQTT будет разработан в виде профилей приложения, специфичных для индустрии, где каждый профиль определить модель угроз и специальные механизмы безопасности, которые будут использоваться для устранения этих угроз. Рекомендации в отношении конкретных механизмов безопасности будут часто приниматься из существующих работ, включая:

[NISTCSF] NIST Cyber Security Framework
[NIST7628] NISTIR 7628 Guidelines for Smart Grid Cyber Security
[FIPS1402] Security Requirements for Cryptographic Modules (FIPS PUB 140-2)
[PCIDSS] PCI-DSS Payment Card Industry Data Security Standard
[NSAB] NSA Suite B Cryptography

[6. Использование WebSocket в качестве сетевого транспорта]

Если MQTT передается поверх соединения WebSocket [RFC6455], то применяются следующие условия:

· MQTT Control Packets ДОЛЖНЫ быть отправлены в двоичных кадрах данных WebSocket. Если получателю пришел любой другой тип кадра, то получатель ДОЛЖЕН закрыть сетевое соединение[MQTT-6.0.0-1].
· Одиночный кадр данных WebSocket может содержать несколько пакетов (MQTT Control Packet), или его части. Получатель НЕ ДОЛЖЕН предполагать, что пакеты MQTT выровнены на границы кадра WebSocket[MQTT-6.0.0-2].
· Клиент ДОЛЖЕН включить "mqtt" в список предполагаемых субпротоколов WebSocket[MQTT-6.0.0-3].
· Выбранное и возвращенное Сервером имя субпротокола ДОЛЖНО быть "mqtt"[MQTT-6.0.0-4].
· WebSocket URI, используемый для подключения Клиента к Серверу, не влияет на протокол MQTT.

6.1. Соображения IANA. Эта спецификация требует от протокола IANA изменить регистрацию субпротокола WebSocket MQTT в реестре "WebSocket Subprotocol Name" следующими данными:

Subprotocol Identifier mqtt
Subprotocol Common Name mqtt
Subprotocol Definition http://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html

Рис. 6.6‑1. IANA WebSocket Identifier.

[7. Соответствие]

Спецификация MQTT определяет соответствие реализаций Клиента MQTT и Сервера MQTT. Реализация MQTT может соответствовать как Клиенту MQTT, так и Серверу MQTT.

7.1. Положения о соответствии.

7.1.1. Соответствие Сервера MQTT. См. выше секцию "Терминология" для определения термина Сервер.

Сервер MQTT соответствует этой спецификации,только если он удовлетворяет приведенным ниже правилам:

1. Соблюдает формат всех посылаемых MQTT Control Packet, который описан в главах 2 и 3.

2. Следует правилам соответствия тем, описанным в разделе 4.7, и правилам подписки в разделе 4.8.

3. Удовлетворяет определенным требованиям уровня ДОЛЖЕН в следующих главах, за исключением тех, что относятся только к Клиенту:

· Глава 1 - Введение
· Глава 2 - Формат пакета управления (MQTT Control Packet)
· Глава 3 - Пакеты управления MQTT
· Глава 4 - Рабочее поведение
· Глава 6 - Использование WebSocket в качестве сетевого транспорта

4. Не требуется использование каких-либо расширений, определенных вне спецификации, для взаимодействия с любой другой соответствующей реализацией.

7.1.2. Соответствие Клиента MQTT. Определение термина Клиент см. выше в секции описания терминологии.

Клиент MQTT соответствует этой спецификации,только если он удовлетворяет приведенным ниже правилам:

1. Соблюдает формат всех посылаемых MQTT Control Packet, который описан в главах 2 и 3.

2. Удовлетворяет определенным требованиям уровня ДОЛЖЕН в следующих главах, за исключением тех, что относятся только к Серверу:

· Глава 1 - Введение
· Глава 2 - Формат пакета управления (MQTT Control Packet)
· Глава 3 - Пакеты управления MQTT
· Глава 4 - Рабочее поведение
· Глава 6 - Использование WebSocket в качестве сетевого транспорта

3. Не требуется использование каких-либо расширений, определенных вне спецификации, для взаимодействия с любой другой соответствующей реализацией.

Это приложение является ненормативным, и предоставляется в виде удобного резюме пронумерованных утверждений о соответствии, содержащихся в основной части настоящего документа. Окончательный перечень требований к соответствию приведен в главе 7.

№ нормативного заявления Нормативное заявление
[MQTT-1.5.4-1] Символьные данные в UTF-8 Encoded String ДОЛЖНЫ быть правильно сформированным UTF-8, как это определено спецификацией Unicode, и уточнено в RFC 3629 [RFC3629]. В частности, символьные данные НЕ ДОЛЖНЫ включать коды между U+D800 и U+DFFF.
[MQTT-1.5.4-2] UTF-8 Encoded String НЕ ДОЛЖНА включать код null-символа U+0000.
[MQTT-1.5.4-3] UTF-8 последовательность 0xEF 0xBB 0xBF всегда интерпретируется как U+FEFF ("ZERO WIDTH NO-BREAK SPACE"), где бы она ни появлялась в строке, и НЕ ДОЛЖНА быть пропущена или вырезана приемником пакета.
[MQTT-1.5.5-1] Закодированное значение ДОЛЖНО использовать минимально необходимое количество байт, которое требуется для представления значения.
[MQTT-1.5.7-1] Обе строки ДОЛЖНЫ удовлетворять требованиям для UTF-8 Encoded Strings.
[MQTT-2.1.3-1] Там, где бит флага помечен как "Зарезервированный", он зарезервирован для использования в будущем, и ДОЛЖЕН быть установлен в указанное спецификацией значение.
[MQTT-2.2.1-2] Пакет PUBLISH НЕ ДОЛЖЕН содержать Packet Identifier, если его значение QoS установлено в 0.
[MQTT-2.2.1-3] Каждый раз, когда Клиент посылает новый пакет SUBSCRIBE, UNSUBSCRIBE или PUBLISH (где QoS > 0) для MQTT Control Packet ДОЛЖЕН быть назначен ненулевой Packet Identifier, который в настоящее время не используется.
[MQTT-2.2.1-4] Каждый раз, когда Сервер посылает новый PUBLISH (с QoS > 0) MQTT Control Packet, ему ДОЛЖЕН быть назначен ненулевой Packet Identifier, который в настоящее время не используется.
[MQTT-2.2.1-5] Пакет PUBACK, PUBREC, PUBREL или PUBCOMP ДОЛЖЕН содержать такой же Packet Identifier, что и оригинально отправленный пакет PUBLISH.
[MQTT-2.2.1-6] Пакеты SUBACK и UNSUBACK ДОЛЖНЫ содержать такой же Packet Identifier, который был в пакете SUBSCRIBE и UNSUBSCRIBE соответственно.
[MQTT-2.2.2-1] Если здесь нет свойств, то это ДОЛЖНО быть показано подключением нулевой длины свойства (Property Length).
[MQTT-3.1.0-1] После того, как было установлено сетевое соединение Клиента с Сервером, первый пакет, отправленный от Клиента, ДОЛЖЕН быть пакетом CONNECT.
[MQTT-3.1.0-2] Сервер ДОЛЖЕН обработать второй пакет CONNECT, отправленный от Клиента, как Protocol Error, и закрыть сетевое соединение.
[MQTT-3.1.2-1] Имя протокола ДОЛЖНО быть UTF-8 String "MQTT". Если Сервер не хочет принять CONNECT, и хочет показать, что это Сервер MQTT, то он МОЖЕТ послать пакет CONNACK с Reason Code of 0x84 (Unsupported Protocol Version), и затем ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.1.2-2] Если Protocol Version не 5, и Сервер не хочет принять пакет CONNECT, то Сервер МОЖЕТ послать пакет CONNACK c Reason Code 0x84 (Unsupported Protocol Version), и затем ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.1.2-3] Сервер ДОЛЖЕН проверить, что зарезервированный флаг в пакете CONNECT установлен в 0.
[MQTT-3.1.2-4] Если принят пакет CONNECT с флагом Clean Start, установленным в 1, то Клиент и Сервер ДОЛЖНЫ отбросить любую существующую сессию и начать новую сессию.
[MQTT-3.1.2-5] Если принят пакет CONNECT с флагом Clean Start, установленным в 0, и существует сессия, ассоциированная с Client Identifier, то Сервер ДОЛЖЕН возобновить коммуникации с Клиентом на базе состояния существующей сессии.
[MQTT-3.1.2-6] Если принят пакет CONNECT с флагом Clean Start, установленным в 0, и не существует сессии, ассоциированной с Client Identifier, то Сервер ДОЛЖЕН создать новую сессию.
[MQTT-3.1.2-7] Если Will Flag установлен в 1, то это означает, что Will Message ДОЛЖНО быть сохранено на Сервере и связано с сессией.
[MQTT-3.1.2-8] Will Message ДОЛЖНО быть опубликовано после последующего закрытия сетевого соединения и истечения интервала Will Delay или завершения сессии, если только Will Message не было удалено Сервером при получении пакета DISCONNECT с Reason Code 0x00 (Normal disconnection), или открыто новое сетевое соединение для ClientID до истечения интервала Will Delay.
[MQTT-3.1.2-9] Если Will Flag установлен в 1, то Сервер будет использовать поля Will QoS и Will Retain в Connect Flags, и поля Will Properties, Will Topic и Will Message ДОЛЖНЫ присутствовать в полезной нагрузке (Payload).
[MQTT-3.1.2-10] Will Message ДОЛЖНО быть удалено из сохраненного Session State на Сервере, как только оно было опубликовано, или Сервер получил от Клиента пакет DISCONNECT с Reason Code 0x00 (Normal disconnection).
[MQTT-3.1.2-11] Если Will Flag установлен в 0, то Will QoS ДОЛЖНО быть установлено в 0 (0x00).
[MQTT-3.1.2-12] Если Will Flag установлен в 1, то значение Will QoS может быть 0 (0x00), 1 (0x01) или 2 (0x02).
[MQTT-3.1.2-13] Если Will Flag установлен в 0, то Will Retain ДОЛЖЕН быть установлен в 0.
[MQTT-3.1.2-14] Если Will Flag установлен в 1, и Will Retain установлен в 0, то Сервер ДОЛЖЕН опубликовать Will Message как non-retained (не сохраняемое) сообщение.
[MQTT-3.1.2-15] Если Will Flag установлен в 1, и Will Retain установлен в 1, то Сервер ДОЛЖЕН опубликовать Will Message как retained (сохраняемое) сообщение.
[MQTT-3.1.2-16] Если флаг User Name установлен в 0, то User Name НЕ ДОЛЖНО присутствовать в полезной нагрузке (Payload).
[MQTT-3.1.2-17] Если флаг User Name установлен в 1, то User Name ДОЛЖНО присутствовать в полезной нагрузке (Payload).
[MQTT-3.1.2-18] Если флаг Password установлен в 0, то Password НЕ ДОЛЖЕН присутствовать в полезной нагрузке (Payload).
[MQTT-3.1.2-19] Если флаг Password установлен в 1, то Password ДОЛЖЕН присутствовать в полезной нагрузке (Payload).
[MQTT-3.1.2-20] Если Keep Alive не 0, и в отсутствие какой-либо отправки других пакетов (MQTT Control Packets) Клиент ДОЛЖЕН послать пакет PINGREQ.
[MQTT-3.1.2-21] Если Сервер возвратил Server Keep Alive в пакете CONNACK, то Клиент ДОЛЖЕН использовать это значение вместо значения, которое Клиент послал как Keep Alive.
[MQTT-3.1.2-22] Если значение Keep Alive не 0, и Сервер не получил MQTT Control Packet от Клиента в течение 1.5 периода времени Keep Alive, то Сервер ДОЛЖЕН закрыть сетевое соединение с Клиентом, как если бы произошел отказ сети.
[MQTT-3.1.2-23] Клиент и Сервер ДОЛЖНЫ сохранять Session State после закрытия сетевого соединения, если Session Expiry Interval больше 0.
[MQTT-3.1.2-24] Сервер НЕ ДОЛЖЕН посылать пакеты Клиенту, размер которых превышает Maximum Packet Size.
[MQTT-3.1.2-25] Когда пакет слишком большой для отправки, Сервер ДОЛЖЕН его отбросить без отправки, и затем вести себя как если бы Application Message было отправлено.
[MQTT-3.1.2-26] Сервер НЕ ДОЛЖЕН посылать Клиенту Topic Alias в пакете PUBLISH, если Topic Alias больше, чем Topic Alias Maximum.
[MQTT-3.1.2-27] Если Topic Alias Maximum отсутствует или 0, то Сервер НЕ ДОЛЖЕН посылать никакие Topic Aliases.
[MQTT-3.1.2-28] Значение 0 показывает, что Сервер НЕ ДОЛЖЕН возвратить Response Information.
[MQTT-3.1.2-29] Если значение Request Problem Information 0, то Сервер МОЖЕТ возвратить Reason String или User Properties в пакете CONNACK или DISCONNECT, но НЕ ДОЛЖЕН посылать Reason String или User Properties в любом пакете, кроме PUBLISH, CONNACK или DISCONNECT.
[MQTT-3.1.2-30] Если Клиент установил Authentication Method в CONNECT, то Клиент НЕ ДОЛЖЕН посылать любые пакеты, кроме пакетов AUTH или DISCONNECT, пока не примет пакет CONNACK.
[MQTT-3.1.3-1] Полезная нагрузка (Payload) пакета CONNECT содержит одно или большее количество полей с префиксом длины, присутствие которых определяется флагами в Variable Header. Эти поля, если они присутствуют, ДОЛЖНЫ появляться в следующем порядке: Client Identifier, Will Topic, Will Message, User Name, Password.
[MQTT-3.1.3-2] ClientID ДОЛЖЕН использоваться Клиентами и Серверами для идентификации состояния, которое они хранят для этой сессии MQTT между Клиентом и Сервером.
[MQTT-3.1.3-3] ClientID ДОЛЖЕН присутствовать, и быть первым полем в полезной нагрузке пакета CONNECT.
[MQTT-3.1.3-4] ClientID ДОЛЖЕН быть UTF-8 Encoded String.
[MQTT-3.1.3-5] Сервер ДОЛЖЕН дозволять ClientID, длина которых между 1 и 23 байт, кодирующих UTF-8, и которые содержат только символы "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ".
[MQTT-3.1.3-6] Сервер МОЖЕТ дозволить клиенту предоставить ClientID длиной в 0 байт, однако тогда Сервер должен обработать это как особый случай и назначить Клиенту уникальный ClientID.
[MQTT-3.1.3-7] Затем Сервер ДОЛЖЕН обработать пакет CONNECT, как если бы Клиент предоставил уникальный ClientID, и ДОЛЖЕН возвратить Assigned Client Identifier в пакете CONNACK.
[MQTT-3.1.3-8] Если Сервер отклонил ClientID, то он МОЖЕТ ответить на пакет CONNECT пакетом CONNACK, используя Reason Code 0x85 (Client Identifier not valid) как описано в секции 4.13 Handling errors, и затем ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.1.3-9] Если сетевое соединение для этой сессии сделано до истечения Will Delay Interval, то Сервер НЕ ДОЛЖЕН посылать Will Message.
[MQTT-3.1.3-10] Сервер ДОЛЖЕН сохранять порядок следования User Properties, когда перенаправляет Application Message.
[MQTT-3.1.3-11] Will Topic ДОЛЖНА быть UTF-8 Encoded String.
[MQTT-3.1.3-12] Если флаг User Name установлен в 1, то User Name является следующим полем в Payload. User Name ДОЛЖНО быть UTF-8 Encoded String.
[MQTT-3.1.4-1] Сервер ДОЛЖЕН проверить, что пакет CONNECT соответствует формату, описанному в секции 3.1, и закрыть сетевое соединение, если он не соответствует.
[MQTT-3.1.4-2] Сервер МОЖЕТ проверить, что содержимое пакета CONNECT удовлетворяет любым дополнительным ограничениям, и возможно ДОЛЖЕН выполнить проверки аутентификации и авторизации. Если любая из этих проверок была неудачной, то он ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.1.4-3] Если ClientID представляет Клиента, который уже подключен к Серверу, то Сервер посылате пакет DISCONNECT существующему Клиенту с Reason Code 0x8E (Session taken over), как этот описано в секции 4.13, и ДОЛЖЕН закрыть сетевое соединение существующего Клиента.
[MQTT-3.1.4-4] Сервер ДОЛЖЕН выполнить обработку Clean Start.
[MQTT-3.1.4-5] Сервер ДОЛЖЕН подтвердить пакет CONNECT пакетом CONNACK, содержащим 0x00 (Success) Reason Code.
[MQTT-3.1.4-6] Если Сервер отклоняет CONNECT, то он НЕ ДОЛЖЕН обрабатывать любые данные, посылаемые Клиентом после CONNECT, кроме пакетов AUTH.
[MQTT-3.2.0-1] Сервер ДОЛЖЕН послать CONNACK с 0x00 (Success) Reason Code перед отправкой любого пакета, отличающегося от AUTH.
[MQTT-3.2.0-2] Сервер НЕ ДОЛЖЕН посылать больше одного CONNACK в сетевом соединении.
[MQTT-3.2.2-1] Байт 1 это "Connect Acknowledge Flags". Биты 7-1 зарезервированы, и ДОЛЖНЫ быть установлены в 0.
[MQTT-3.2.2-2] Если Сервер принял соединение с Clean Start, установленным в 1, то Сервер ДОЛЖЕН установить Session Present в 0 пакета CONNACK в дополнение к установке 0x00 (Success) Reason Code в пакете CONNACK.
[MQTT-3.2.2-3] Если Сервер принял соединение с Clean Start, установленным в 0, и у Сервера есть Session State для ClientID, то он ДОЛЖЕН установить Session Present 1 в пакете CONNACK, иначе ДОЛЖЕН установить Session Present 0 в пакете CONNACK. В обоих случаях он ДОЛЖЕН установить 0x00 (Success) Reason Code в пакете CONNACK.
[MQTT-3.2.2-4] Если у Клиента нет Session State, и он получит Session Present, установленный в 1, то он ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.2.2-5] Если у Клиента есть Session State, и он получит Session Present, установленный в 0, то он ДОЛЖЕН отбросить свое Session State, если он продолжает работу с сетевым соединением.
[MQTT-3.2.2-6] Если Сервер послал пакет CONNACK, содержащий ненулевой Reason Code, то он ДОЛЖЕН установить Session Present в 0.
[MQTT-3.2.2-7] Если Сервер послал пакет CONNACK, содержащий Reason Code 0x80 или больше, то он ДОЛЖЕН тогда закрыть сетевое соединение.
[MQTT-3.2.2-8] Сервер, посылающий пакет CONNACK, ДОЛЖЕН использовать одно из значений Connect Reason Code.
[MQTT-3.2.2-9] Если Сервер не поддерживает QoS1 или QoS2 пакетов PUBLISH, то он ДОЛЖЕН установить Maximum QoS в пакете CONNACK, указывающий самый высокий поддерживаемый уровень QoS.
[MQTT-3.2.2-10] Сервер, который не поддерживает QoS1 или QoS2 пакетов PUBLISH, все еще ДОЛЖЕН принимать пакеты SUBSCRIBE, содержащие запрашиваемые QoS уровней 0, 1 или 2.
[MQTT-3.2.2-11] Если Клиент принял Maximum QoS от Сервера, то он НЕ ДОЛЖЕН посылать пакеты PUBLISH с уровнем QoS, превышающим указанный уровень Maximum QoS.
[MQTT-3.2.2-12] Если Сервер примет пакет CONNECT, содержащий Will QoS, который превышает его возможности, то он ДОЛЖЕН отклонить соединение. Он возможно ДОЛЖЕН использовать пакет CONNACK с Reason Code 0x9B (QoS not supported), как это описано в секции 4.13 Handling errors, и ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.2.2-13] Если Сервер получил пакет CONNECT, содержащий Will Message с Will Retain 1, и Сервер не поддерживает сохраняемые сообщения (retained messages), то Сервер ДОЛЖЕН отклонить запрос на соединение. Он возможно ДОЛЖЕН послать CONNACK с Reason Code 0x9A (Retain not supported), и затем ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.2.2-14] Клиент, получивший от Сервера Retain Available, установленный в 0, НЕ ДОЛЖЕН посылать пакет PUBLISH с флагом RETAIN, установленным в 1.
[MQTT-3.2.2-15] Клиент НЕ ДОЛЖЕН посылать Серверу пакеты, превышающие Maximum Packet Size.
[MQTT-3.2.2-16] Если Клиент подключается, используя Client Identifier нулевой длины, то Сервер ДОЛЖЕН ответить пакетом CONNACK, содержащий назначенный идентификатор для клиента (Assigned Client Identifier). Этот идентификатор ДОЛЖЕН быть новым Client Identifier, который не используется в настоящий момент Сервером ни в какой другой сессии.
[MQTT-3.2.2-17] Клиент НЕ ДОЛЖЕН посылать Серверу Topic Alias в пакете PUBLISH больше, чем это значение.
[MQTT-3.2.2-18] Topic Alias Maximum отсутствует, Клиент НЕ ДОЛЖЕН посылать Серверу никакие Topic Alias.
[MQTT-3.2.2-19] Сервер НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета CONNACK сверх Maximum Packet Size, указанного Клиентом.
[MQTT-3.2.2-20] Сервер НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета CONNACK сверх Maximum Packet Size, указанного Клиентом.
[MQTT-3.2.2-21] Если Сервер посылает Server Keep Alive на пакете CONNACK, то Клиент ДОЛЖЕН использовать это значение вместо значения Keep Alive, которое Клиент послал в пакете CONNECT.
[MQTT-3.2.2-22] Если Сервер не послал Server Keep Alive, то Сервер ДОЛЖЕН использовать MUST значение Keep Alive, установленное Клиентом в пакете CONNECT.
[MQTT-3.3.1-1] Флаг DUP ДОЛЖЕН быть установлен в 1 Клиентом или Сервером, когда они пытаются повторно доставить пакет PUBLISH.
[MQTT-3.3.1-2] Флаг DUP ДОЛЖЕН быть установлен в 0 для всех сообщений QoS0.
[MQTT-3.3.1-3] Флаг DUP в исходящем пакете PUBLISH устанавливается независимо от приходящего пакета PUBLISH, его значение ДОЛЖНО быть полностью определено исключительно тем, является ли исходящий пакет PUBLISH повторной передачей.
[MQTT-3.3.1-4] Пакет PUBLISH НЕ ДОЛЖЕН иметь оба бита QoS, установленных в 1.
[MQTT-3.3.1-5] Если флаг RETAIN пакета PUBLISH, отправленного Клиентом на Сервер, установлен в 1, то Сервер ДОЛЖЕН заменить любое существующее retained message для этой темы и сохранить Application Message.
[MQTT-3.3.1-6] Если Payload содержит 0 байт, то это нормально обрабатывается Сервером, но любое retained message с таким же именем темы ДОЛЖНО быть удалено, и любые будущие подписчики для этой темы не получат сохраненное сообщение (retained message).
[MQTT-3.3.1-7] Retained message c Payload, содержащей 0 байт, НЕ ДОЛЖНО быть сохранено на Сервере как retained message.
[MQTT-3.3.1-8] Если флаг RETAIN 0 в пакете PUBLISH, отправленном Клиентом на Сервер, то Сервер НЕ ДОЛЖЕН сохранять сообщение как retained message, и НЕ ДОЛЖЕН удалять или заменять любое существующее retained message.
[MQTT-3.3.1-9] Если Retain Handling установлено в 0, то Сервер ДОЛЖЕН послать Клиенту retained messages, совпадающие с Topic Filter подписки.
[MQTT-3.3.1-10] Если Retain Handling установлено в 1, то если подписка уже существует, то Сервер ДОЛЖЕН послать Клиенту все retained messages, соответствующие Topic Filter подписки, и если подписка не существует, то Сервер НЕ ДОЛЖЕН посылать сохраненные сообщения.
[MQTT-3.3.1-11] Если Retain Handling установлено в 2, то Сервер НЕ ДОЛЖЕН посылать retained messages.
[MQTT-3.3.1-12] Если значение Retain As Published опции подписки установлено в 0, то Сервер ДОЛЖЕН установить флаг RETAIN в 0, когда перенаправляет Application Message, независимо от того, как был установлен флаг RETAIN в принятом пакете PUBLISH.
[MQTT-3.3.1-13] Если значение Retain As Published опции подписки установлено в 1, то Сервер ДОЛЖЕН установить флаг RETAIN эквивалентно флагу RETAIN в принятом пакете PUBLISH.
[MQTT-3.3.2-1] Topic Name ДОЛЖНО присутствовать как первое поле в Variable Header пакета PUBLISH. Оно ДОЛЖНО быть UTF-8 Encoded String.
[MQTT-3.3.2-2] Topic Name в пакете PUBLISH НЕ ДОЛЖНО содержать символы wildcard.
[MQTT-3.3.2-3] Topic Name в пакете PUBLISH, отправленном Сервером подписавшемуся Клиенту, ДОЛЖНО совпадать с фильтром темы подписки (Subscription Topic Filter).
[MQTT-3.3.2-4] Сервер ДОЛЖЕН послать Payload Format Indicator неизмененным всем подписчикам, получающим сообщение.
[MQTT-3.3.2-5] Если истек Message Expiry Interval, и Серверу не удалось начать дальнейшую доставку соответствующему подписчику, затем он ДОЛЖЕН удалить копию сообщения для этого подписчика.
[MQTT-3.3.2-6] Пакет PUBLISH, отправленный Клиенту Сервером, ДОЛЖЕН содержать Message Expiry Interval, установленный в принятое значение минус время, которое сообщение ожидало на Сервере.
[MQTT-3.3.2-7] Получатель НЕ ДОЛЖЕН переносить любые сопоставления псевдонимов тем (Topic Alias) из одного сетевого подключения в другое.
[MQTT-3.3.2-8] Отправитель НЕ ДОЛЖЕН посылать пакет PUBLISH, содержащий Topic Alias со значением 0.
[MQTT-3.3.2-9] Клиент НЕ ДОЛЖЕН посылать пакет PUBLISH с Topic Alias большим, чем значение Topic Alias Maximum, возвращенное сервером в пакете CONNACK.
[MQTT-3.3.2-10] Клиент ДОЛЖЕН принять все значения Topic Alias, большие 0, и меньшие или равные Topic Alias Maximum, которые он послал в пакете CONNECT.
[MQTT-3.3.2-11] Сервер НЕ ДОЛЖЕН посылать пакет PUBLISH с Topic Alias, большим чем значение Topic Alias Maximum, посланном Клиентом в пакете CONNECT.
[MQTT-3.3.2-12] Сервер ДОЛЖЕН принять все значения Topic Alias, большие чем 0 и меньшие или равные Topic Alias Maximum, который он возвратил в пакете CONNACK.
[MQTT-3.3.2-13] Response Topic ДОЛЖЕН быть UTF-8 Encoded String.
[MQTT-3.3.2-14] Response Topic НЕ ДОЛЖЕН содержать символы wildcard.
[MQTT-3.3.2-15] Сервер ДОЛЖЕН послать Response Topic неизмененным всем подписчикам, принимающим Application Message.
[MQTT-3.3.2-16] Сервер ДОЛЖЕН послать Correlation Data не измененными всем подписчикам, принимающим Application Message.
[MQTT-3.3.2-17] Сервер ДОЛЖЕН послать все User Properties не измененными в пакете PUBLISH, когда он перенаправляет Application Message Клиенту.
[MQTT-3.3.2-18] Сервер ДОЛЖЕН сохранять порядок следования User Properties, когда перенаправляет Application Message.
[MQTT-3.3.2-19] Content Type ДОЛЖНО быть UTF-8 Encoded String.
[MQTT-3.3.2-20] Сервер ДОЛЖЕН посылать Content Type неизмененным всем подписчикам, принимающим Application Message.
[MQTT-3.3.4-1] Получатель пакета PUBLISH ДОЛЖЕН ответить пакетом, как это определено QoS в пакете PUBLISH.
[MQTT-3.3.4-2] В этом случае Сервер ДОЛЖЕН доставить сообщение Клиенту с учетом максимального QoS всех совпавших подписок.
[MQTT-3.3.4-3] Если Клиент указал идентификатор подписки (Subscription Identifier) для любой из перекрывающихся подписок, то Сервер ДОЛЖЕН отправить эти идентификаторы подписки в сообщении, которое публикуется в результате подписок.
[MQTT-3.3.4-4] Если Сервер посылает одну копию сообщения, то он ДОЛЖЕН подключить в пакет PUBLISH идентификаторы подписки для всех совпавших подписок, у которых есть идентификаторы подписки, их порядок следования не имеет значения.
[MQTT-3.3.4-5] Если Сервер посылает несколько пакетов PUBLISH, то он ДОЛЖЕН послать в каждом из них идентификатор совпавшей подписки, если у него есть идентификатор подписки.
[MQTT-3.3.4-6] Пакет PUBLISH, отправленный Клиентом Серверу, НЕ ДОЛЖЕН содержать Subscription Identifier.
[MQTT-3.3.4-7] Клиент НЕ ДОЛЖЕН посылать больше чем Receive Maximum QoS1 и QoS2 пакеты PUBLISH, для которых от сервера не приняты пакеты PUBACK, PUBCOMP или PUBREC с Reason Code 128 или больше.
[MQTT-3.3.4-8] Клиент НЕ ДОЛЖЕН задерживать отправку любых пакетов, отличающихся от пакетов PUBLISH, из-за отправки Receive Maximum пакетов PUBLISH без приема для них подтверждений.
[MQTT-3.3.4-9] Сервер НЕ ДОЛЖЕН посылать больше чем Receive Maximum QoS1 и QoS 2 пакетов PUBLISH, для которых от Клиента не были получены пакеты PUBACK, PUBCOMP или PUBREC с Reason Code 128 или больше.
[MQTT-3.3.4-10] Сервер НЕ ДОЛЖЕН задерживать отправку любых пакетов, отличающихся от пакетов PUBLISH, из-за отправки Receive Maximum пакетов PUBLISH без приема для них подтверждений.
[MQTT-3.4.2-1] Клиент или Сервер, посылающий пакет PUBACK, ДОЛЖЕН использовать один из PUBACK Reason Codes.
[MQTT-3.4.2-2] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета PUBACK сверх Maximum Packet Size, указанного получателем.
[MQTT-3.4.2-3] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета PUBACK сверх Maximum Packet Size, указанного получателем.
[MQTT-3.5.2-1] Клиент или Сервер, посылающий пакет PUBREC, ДОЛЖЕН использовать один из PUBREC Reason Codes.
[MQTT-3.5.2-2] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета PUBREC сверх Maximum Packet Size, указанного получателем.
[MQTT-3.5.2-3] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета PUBREC сверх Maximum Packet Size, указанного получателем.
[MQTT-3.6.1-1] Биты 3, 2, 1 и 0 в Fixed Header пакета PUBREL зарезервированы, и ДОЛЖНЫ быть установлены в 0, 0, 1 и 0 соответственно. Сервер ДОЛЖЕН обрабатывать любое другое значение как ошибочный пакет и ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.6.2-1] Клиент или Сервер, посылающий пакет PUBREL, ДОЛЖЕН использовать один из PUBREL Reason Codes.
[MQTT-3.6.2-2] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета PUBREL сверх Maximum Packet Size, указанного получателем.
[MQTT-3.6.2-3] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета PUBREL сверх Maximum Packet Size, указанного получателем.
[MQTT-3.7.2-1] Клиент или Сервер, посылающий пакет PUBCOMP, ДОЛЖЕН использовать один из PUBCOMP Reason Codes.
[MQTT-3.7.2-2] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета PUBCOMP сверх Maximum Packet Size, указанного получателем.
[MQTT-3.7.2-3] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета PUBCOMP сверх Maximum Packet Size, указанного получателем.
[MQTT-3.8.1-1] Биты 3, 2, 1 и 0 в Fixed Header пакета SUBSCRIBE зарезервированы, и ДОЛЖНЫ быть установлены в 0, 0, 1 и 0 соответственно. Сервер ДОЛЖЕН обрабатывать любое другое значение как ошибочный пакет и ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.8.3-1] Topic Filters ДОЛЖНЫ быть UTF-8 Encoded String.
[MQTT-3.8.3-2] Payload ДОЛЖНА содержать как минимум одну пару Topic Filter и Subscription Options.
[MQTT-3.8.3-3] Бит 2 опций подписки (Subscription Options) представляет опцию No Local. Если у неё значение 1, то Application Messages НЕ ДОЛЖНЫ перенаправляться на соединение с ClientID, равным ClientID соединения публикации.
[MQTT-3.8.3-4] Считается Protocol Error для установки в 1 бита No Local на общей подписке (Shared Subscription).
[MQTT-3.8.3-5] Сервер ДОЛЖЕН обработать пакет SUBSCRIBE как ошибочно сформированный, если любой из зарезервированных бит в Payload не равны 0.
[MQTT-3.8.4-1] Когда Сервер принял пакет SUBSCRIBE от Клиента, Сервер должен ответить на это пакетом SUBACK.
[MQTT-3.8.4-2] Пакет SUBACK ДОЛЖЕН иметь такой же Packet Identifier, как и подтверждаемый пакет SUBSCRIBE.
[MQTT-3.8.4-3] Если Сервер принял пакет SUBSCRIBE, содержащий Topic Filter, идентичный Topic Filter частной подписки (Non-shared Subscription) для текущей сессии, то он ДОЛЖЕН заменить существующую подписку на новую.
[MQTT-3.8.4-4] Если опция Retain Handling установлена в 0, то любое существующее retained message, совпадающее с Topic Filter, ДОЛЖНО быть отправлено заново, но Application Messages НЕ ДОЛЖНЫ быть потеряны из-за замены подписки.
[MQTT-3.8.4-5] Если Сервер получил пакет SUBSCRIBE, который содержит несколько Topic Filter, то он ДОЛЖЕН обработать этот пакет как если бы он принял последовательность из нескольких пакетов SUBSCRIBE, с тем лишь исключением, что Сервер скомбинирует ответы на них в одном ответе SUBACK.
[MQTT-3.8.4-6] Пакет SUBACK, отправленный Сервером, ДОЛЖЕН содержать Reason Code для каждой пары Topic Filter/Subscription Option.
[MQTT-3.8.4-7] Этот Reason Code ДОЛЖЕН либо показывать, что maximum QoS был предоставлен, либо показывать, что подписка была неудачной.
[MQTT-3.8.4-8] QoS полезной нагрузки сообщений, отправленных в ответ на подписку, ДОЛЖЕН быть минимальным QoS между оригинальным опубликованным сообщением и Maximum QoS, предоставленным Сервером.
[MQTT-3.9.2-1] Сервер НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета SUBACK сверх Maximum Packet Size, указанного клиентом.
[MQTT-3.9.2-2] Сервер НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета SUBACK сверх Maximum Packet Size, указанного клиентом.
[MQTT-3.9.3-1] Порядок следования Reason Codes в пакете SUBACK ДОЛЖЕН совпадать с порядком следования Topic Filter в пакете SUBSCRIBE.
[MQTT-3.9.3-2] Сервер, отправляющий пакет SUBACK, ДОЛЖЕН послать одно из значений Subscribe Reason Code для каждого принятого Topic Filter.
[MQTT-3.10.1-1] Биты 3, 2, 1 и 0 в Fixed Header пакета UNSUBSCRIBE зарезервированы, и ДОЛЖНЫ быть установлены в 0, 0, 1 и 0 соответственно. Сервер ДОЛЖЕН обрабатывать любое другое значение как ошибочный пакет и ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.10.3-1] Topic Filters в пакете UNSUBSCRIBE ДОЛЖНЫ быть UTF-8 Encoded Strings.
[MQTT-3.10.3-2] Полезная нагрузка пакета UNSUBSCRIBE ДОЛЖНА содержать как минимум один Topic Filter.
[MQTT-3.10.4-1] Фильтры тем (независимо от того, содержат ли они символы wildcard, или нет), предоставленные в пакете UNSUBSCRIBE, ДОЛЖНЫ быть посимвольно сравнены с текущим набором Topic Filter, который Сервер хранит для Клиента. Если любой фильтр точно совпадает, то содержащая его подписка ДОЛЖНА быть удалена.
[MQTT-3.10.4-2] Когда Сервер примет UNSUBSCRIBE, он ДОЛЖЕН остановить добавление любых новых сообщений, которые соответствуют Topic Filters, для доставки Клиенту.
[MQTT-3.10.4-3] Когда Сервер примет UNSUBSCRIBE, он ДОЛЖЕН завершить доставку любых сообщений QoS1 или QoS2, которые совпадают с Topic Filters, и отправка которых начата Клиенту.
[MQTT-3.10.4-4] Сервер ДОЛЖЕН ответить на запрос UNSUBSCRIBE отправкой пакета UNSUBACK.
[MQTT-3.10.4-5] Пакет UNSUBACK ДОЛЖЕН иметь такой же Packet Identifier, как и пакет UNSUBSCRIBE. Даже когда ни одна из Topic Subscription не была удалена, Сервер ДОЛЖЕН ответить пакетом UNSUBACK.
[MQTT-3.10.4-6] Если Сервер принял пакет UNSUBSCRIBE, который содержит несколько Topic Filters, то он должен обработать этот пакет как если бы это была последовательность из нескольких пакетов UNSUBSCRIBE, за исключением того, что он ответит на все эти пакеты одним пакетом UNSUBACK.
[MQTT-3.11.2-1] Сервер НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета UNSUBACK сверх Maximum Packet Size, указанного клиентом.
[MQTT-3.11.2-2] Сервер НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета UNSUBACK сверх Maximum Packet Size, указанного получателем.
[MQTT-3.11.3-1] Порядок следования Reason Codes в пакете UNSUBACK ДОЛЖЕН соответствовать порядку следования Topic Filters в пакете UNSUBSCRIBE.
[MQTT-3.11.3-2] Сервер, посылающий пакет UNSUBACK, ДОЛЖЕН использовать одно из значений UNSUBSCRIBE Reason Code для каждого принятого Topic Filter.
[MQTT-3.12.4-1] Сервер ДОЛЖЕН отправить пакет PINGRESP в ответ на пакет PINGREQ.
[MQTT-3.14.0-1] Сервер НЕ ДОЛЖЕН посылать DISCONNECT после того, как он отправил CONNACK с Reason Code меньше 0x80.
[MQTT-3.14.1-1] Клиент или Сервер ДОЛЖНЫ проверить зарезервированные биты, что они установлены в 0. Если они не установлены в 0, то они посылают пакет DISCONNECT с Reason Code 0x81 (Malformed Packet).
[MQTT-3.14.2-1] Клиент или Сервер, посылающий пакет DISCONNECT, ДОЛЖЕН использовать один из DISCONNECT Reason Code.
[MQTT-3.14.2-2] Session Expiry Interval НЕ ДОЛЖЕН посылаться Сервером в пакете DISCONNECT.
[MQTT-3.14.2-3] Отправитель НЕ ДОЛЖЕН использовать это свойство, если это увеличит размер пакета DISCONNECT сверх Maximum Packet Size, указанного получателем.
[MQTT-3.14.2-4] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета DISCONNECT сверх Maximum Packet Size, указанного получателем.
[MQTT-3.14.4-1] После отправки пакета DISCONNECT отправитель НЕ ДОЛЖЕН посылать больше никакие MQTT Control Packet на этом сетевом соединении.
[MQTT-3.14.4-2] После отправки пакета DISCONNECT отправитель ДОЛЖЕН закрыть сетевое соединение.
[MQTT-3.14.4-3] На приеме пакета DISCONNECT с Reason Code 0x00 (Success) Сервер ДОЛЖЕН отбросить любые Will Message, ассоциированные с текущим соединением без их публикации.
[MQTT-3.15.1-1] Биты 3, 2, 1 и 0 Fixed Header пакета AUTH зарезервированы и ДОЛЖНЫ быть все установлены в 0. Клиент или Сервер ДОЛЖНЫ обработать любое другое значение как ошибочно сформированный пакет и закрыть сетевое соединение.
[MQTT-3.15.2-1] Отправитель пакета AUTH ДОЛЖЕН использовать один из Authenticate Reason Codes.
[MQTT-3.15.2-2] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета AUTH сверх Maximum Packet Size, указанного получателем.
[MQTT-3.15.2-3] Отправитель НЕ ДОЛЖЕН посылать это свойство, если это увеличит размер пакета AUTH сверх Maximum Packet Size, указанного получателем.
[MQTT-4.1.0-1] Клиент и Сервер НЕ ДОЛЖНЫ отбрасывать Session State, пока открыто сетевое соединение.
[MQTT-4.2.0-1] Клиент или Сервер ДОЛЖНЫ поддерживать один или большее количество нижележащих транспортных протоколов, которые обеспечивают упорядоченный, без потерь поток байт от Клиента к Серверу и от Сервера к Клиенту.
[MQTT-4.1.0-2] Сервер ДОЛЖЕН отбросить Session State, когда сетевое соединение закрыто, и истек интервал времени жизни сессии (Session Expiry Interval).
[MQTT-4.3.1-1] В протоколе доставки QoS0 отправитель ДОЛЖЕН отправить пакет PUBLISH с QoS0 и флагом DUP, установленным в 0.
[MQTT-4.3.2-1] В протоколе доставки QoS1 отправитель ДОЛЖЕН назначить неиспользуемый Packet Identifier каждый раз при публикации нового Application Message.
[MQTT-4.3.2-2] В протоколе доставки QoS1 отправитель ДОЛЖЕН послать пакет PUBLISH, содержащий Packet Identifier с QoS1 и флаг DUP, установленный в 0.
[MQTT-4.3.2-3] В протоколе доставки QoS1 отправитель ДОЛЖЕН обработать пакет PUBLISH как "не подтвержденный" (unacknowledged), пока не примет соответствующий пакет PUBACK от получателя.
[MQTT-4.3.2-4] В протоколе доставки QoS1 получатель ДОЛЖЕН ответить пакетом PUBACK, содержащим Packet Identifier из поступившего пакета PUBLISH, подтверждая тем самым вступление во владение полученным Application Message.
[MQTT-4.3.2-5] В протоколе доставки QoS1 получатель, после того как он отправил пакет PUBACK, он ДОЛЖЕН обработать любой приходящий пакет PUBLISH, содержащий такой же идентификатор, как новое Application Message, независимо от установки его флага DUP.
[MQTT-4.3.3-1] В протоколе доставки QoS2 отправитель ДОЛЖЕН назначить не используемый Packet Identifier, когда имеется для публикации новое Application Message.
[MQTT-4.3.3-2] В протоколе доставки QoS2 отправитель ДОЛЖЕН отправить пакет PUBLISH, содержащий этот Packet Identifier с QoS2 и флагом DUP, установленным в 0.
[MQTT-4.3.3-3] В протоколе доставки QoS2 отправитель ДОЛЖЕН обработать пакет PUBLISH как "не подтвержденный" (unacknowledged), пока не получит соответствующий пакет PUBREC от получателя.
[MQTT-4.3.3-4] В протоколе доставки QoS2 отправитель ДОЛЖЕН послать пакет PUBREL, когда он принял пакет PUBREC от получателя со значением Reason Code меньше 0x80. Этот пакет PUBREL ДОЛЖЕН содержать такой же Packet Identifier, как и оригинальный пакет PUBLISH.
[MQTT-4.3.3-5] В протоколе доставки QoS2 отправитель ДОЛЖЕН обработать пакет PUBREL как "не подтвержденный" (unacknowledged), пока не будет принят соответствующий пакет PUBCOMP от получателя.
[MQTT-4.3.3-6] В протоколе доставки QoS2 отправитель НЕ ДОЛЖЕН NOT повторно отправлять пакет PUBLISH после того как он отправил соответствующий пакет PUBREL.
[MQTT-4.3.3-7] В протоколе доставки QoS2 отправитель НЕ ДОЛЖЕН NOT применять устаревание Application Message, если был отправлен пакет PUBLISH.
[MQTT-4.3.3-8] В протоколе доставки QoS2 получатель ДОЛЖЕН ответить пакетом PUBREC, содержащим Packet Identifier из поступившего пакета PUBLISH, подтверждая тем самым вступление во владение полученным Application Message.
[MQTT-4.3.3-9] В протоколе доставки QoS2 получатель, если он отправил PUBREC с Reason Code 0x80 или больше, то он ДОЛЖЕН обработать любой последующий пакет PUBLISH, который содержит этот Packet Identifier, как новое Application Message.
[MQTT-4.3.3-10] В протоколе доставки QoS2 получатель, пока он не примет соответствующий пакет PUBREL, он ДОЛЖЕН подтверждать любой последующий пакет PUBLISH с таким же Packet Identifier путем отправки PUBREC. В этом случае он НЕ ДОЛЖЕН вызывать доставку повторяющихся сообщений другим получателям.
[MQTT-4.3.3-11] В протоколе доставки QoS2 получатель ДОЛЖЕН ответить на пакет PUBREL отправкой пакета PUBCOMP, содержащего такой же Packet Identifier, как был в пакете PUBREL.
[MQTT-4.3.3-12] В протоколе доставки QoS2 получатель, после того ка он отправил PUBCOMP, он ДОЛЖЕН обрабатывать любые последующие пакеты PUBLISH, которые содержат этот Packet Identifier, как новое Application Message.
[MQTT-4.3.3-13] В протоколе доставки QoS2 получатель ДОЛЖЕН продолжить последовательность подтверждения QoS2, даже если было применено устаревание Application Message.
[MQTT-4.4.0-1] Когда Клиент подключается повторно с Clean Start, установленным в 0, и существует сессия, от оба и Клиент и Сервер ДОЛЖНЫ повторно отправить любые не подтвержденные пакеты PUBLISH (у которых QoS > 0) и пакеты PUBREL, используя их оригинальные идентификаторы пакета (Packet Identifier). Это единственное обстоятельство, при котором Клиент или Сервер ОБЯЗАНЫ отправлять сообщения повторно. Клиенты и Серверы НЕ ДОЛЖНЫ повторно отправлять сообщения в любое другое время.
[MQTT-4.4.0-2] Если принятые PUBACK или PUBREC содержат Reason Code 0x80 или больше, то соответствующий пакет PUBLISH считается подтвержденным, и НЕ ДОЛЖЕН быть отправлен повторно.
[MQTT-4.5.0-1] Когда Сервер принимает во владение поступившее Application Message, он ДОЛЖЕН добавить его в Session State для клиентов, у которых есть соответствующие подписки.
[MQTT-4.5.0-2] Клиент ДОЛЖЕН подтвердить любой пакет PUBLISH, который он принял, в соответствии с применимыми правилами QoS, независимо от того, выбирает ли он обработку Application Message, которое пакет содержит.
[MQTT-4.6.0-1] Когда Клиент повторно отправляет любые пакеты PUBLISH, он ДОЛЖЕН отправить их в том же порядке, в каком были отправлены оригинальные пакеты PUBLISH (это применимо к сообщениям QoS1 и QoS2).
[MQTT-4.6.0-2] Клиент ДОЛЖЕН отправить пакеты PUBACK в том же порядке, к котором были приняты соответствующие пакеты PUBLISH (сообщений QoS1).
[MQTT-4.6.0-3] Клиент ДОЛЖЕН отправить пакеты PUBREC в том же порядке, к котором были приняты соответствующие пакеты PUBLISH (сообщений QoS2).
[MQTT-4.6.0-4] Клиент ДОЛЖЕН отправить пакеты PUBREL в том же порядке, к котором были приняты соответствующие пакеты PUBREC (сообщений QoS2).
[MQTT-4.6.0-5] Когда Сервер обрабатывает сообщения, которые опубликованы в упорядоченную тему (Ordered Topic), он ДОЛЖЕН посылать пакеты PUBLISH потребителям (для тех же темы и QoS) в том же порядке, в котором они были получены от данного Клиента.
[MQTT-4.6.0-6] Сервер ДОЛЖЕН рассматривать каждую тему (Topic) как упорядоченную тему (Ordered Topic), когда он пересылает сообщения по частным подпискам (Non-shared Subscriptions).
[MQTT-4.7.0-1] В фильтрах тем (Topic Filters) могут использоваться символы wildcard, но они НЕ ДОЛЖНЫ использоваться в имени темы (Topic Name).
[MQTT-4.7.1-1] Многоуровневый символ wildcard ДОЛЖЕН быть указан либо на своем собственном, либо следующем разделителе уровня темы. В любом случае он ДОЛЖЕН быть последним символом, указанным в Topic Filter.
[MQTT-4.7.1-2] Одноуровневый символ wildcard может использоваться на любом уровне в Topic Filter, включая первый и последний уровни. Там, где он используется, он ДОЛЖЕН занимать весь уровень фильтра.
[MQTT-4.7.2-1] Сервер НЕ ДОЛЖЕН сопоставлять фильтры тем (Topic Filters), начиная с символа wildcard (# или +) с именами тем (Topic Names), которые начинаются на символ $.
[MQTT-4.7.3-1] Все имена тем (Topic Names) и фильтры тем (Topic Filters) ДОЛЖНЫ быть длиной как минимум в 1 символ.
[MQTT-4.7.3-2] Topic Names и Topic Filters НЕ ДОЛЖНЫ включать символ null (Unicode U+0000).
[MQTT-4.7.3-3] Topic Names и Topic Filters это строки в формате UTF-8 Encoded Strings; они НЕ ДОЛЖНЫ кодировать больше чем 65535 байт.
[MQTT-4.7.3-4] Когда выполняется подписка, соответствующий Сервер НЕ ДОЛЖЕН выполнять никакую нормализацию имен тем (Topic Names) или фильтров тем (Topic Filters), или выполнять любую модификацию или замену не распознанных символов.
[MQTT-4.8.2-1] Фильтр темы общей подписки (Shared Subscription Topic Filter) ДОЛЖЕН начинаться на $share/, и ДОЛЖЕН содержать ShareName длиной как минимум 1 символ.
[MQTT-4.8.2-2] ShareName НЕ ДОЛЖНО содержать символы "/", "+" или "#", однако ДОЛЖНО заканчиваться символом "/". Этот символ "/" ДОЛЖЕН следовать за Topic Filter.
[MQTT-4.8.2-3] Сервер ДОЛЖЕН соблюдать предоставленный уровень QoS для подписки Клиентов.
[MQTT-4.8.2-4] Сервер ДОЛЖЕН выполнять доставку сообщения Клиенту, когда он подключается заново.
[MQTT-4.8.2-5] Если сессия Клиента завершается до того, как Клиент подключится заново, то Сервер НЕ ДОЛЖЕН посылать Application Message любому другому подписавшемуся Клиенту.
[MQTT-4.8.2-6] Если Клиент ответил на пакет PUBLISH от Сервера пакетом PUBACK или PUBREC, содержащим Reason Code 0x80 или больше, то Сервер ДОЛЖЕН отбросить Application Message и не пытаться отправить его любому другому подписчику.
[MQTT-4.9.0-1] Клиент или Сервер ДОЛЖЕН установить свою начальную квоту отправки в ненулевое значение, не превышающее Receive Maximum.
[MQTT-4.9.0-2] Каждый раз, когда Клиент или Сервер посылает пакет PUBLISH с QoS > 0, он декрементирует квоту отправки. Если квота отправки достигла 0, то Клиент или Сервер НЕ ДОЛЖЕН посылать больше пакеты PUBLISH с QoS > 0.
[MQTT-4.9.0-3] Клиент и Сервер ДОЛЖЕН продолжить обработку и отвечать на все другие пакеты (MQTT Control Packets), даже если квота нулевая.
[MQTT-4.12.0-1] Если Сервер не поддерживает Authentication Method, предоставленный Клиентом, то он МОЖЕТ послать CONNACK с Reason Code 0x8C (Bad authentication method) или 0x87 (Not Authorized), как это описано в секции 4.13, и ДОЛЖЕН закрыть сетевое соединение.
[MQTT-4.12.0-2] Если Сервер требует дополнительную информацию для завершения авторизации, то он может послать Клиенту пакет AUTH. Этот пакет ДОЛЖЕН содержать Reason Code 0x18 (Continue authentication).
[MQTT-4.12.0-3] Клиент ответит на пакет AUTH, поступивший от Сервера, отправкой следующего пакета AUTH. Этот пакет ДОЛЖЕН содержать Reason Code 0x18 (Continue authentication).
[MQTT-4.12.0-4] Сервер может отклонить аутентификацию в любой момент этого процесса. Он МОЖЕТ послать пакет CONNACK с Reason Code 0x80 или больше, как это описано в секции 4.13, и ДОЛЖЕН закрыть сетевое соединение.
[MQTT-4.12.0-5] Если изначальный пакет CONNECT включает свойство Authentication Method, то все пакеты AUTH и любой успешный пакет CONNACK ДОЛЖЕН включать свойство Authentication Method с таким же значением, как было в пакете CONNECT.
[MQTT-4.12.0-6] Если Клиент не включил Authentication Method в CONNECT, то Сервер НЕ ДОЛЖЕН посылать пакет AUTH, и он НЕ ДОЛЖЕН посылать Authentication Method в пакете CONNACK.
[MQTT-4.12.0-7] Если Клиент не включил Authentication Method в CONNECT, то Клиент НЕ ДОЛЖЕН посылать пакет AUTH Серверу.
[MQTT-4.12.1-1] Если Клиент предоставил Authentication Method в пакете CONNECT, то он может инициировать повторную аутентификацию в любой момент после получения CONNACK. Он делает это отправкой пакета AUTH с Reason Code 0x19 (Re-authentication). Клиент ДОЛЖЕН установить Authentication Method в то же значение, как оригинальное значение Authentication Method, которое изначально использовалось при аутентификации сетевого соединения.
[MQTT-4.12.1-2] Если повторная аутентификация завершилась неудачей, то Клиент или Сервер возможно ДОЛЖНЫ послать пакет DISCONNECT с подходящим Reason Code, и ДОЛЖНЫ закрыть сетевое соединение.
[MQTT-4.13.1-1] Когда Сервер определил неправильно сформированный пакет (Malformed Packet) или ошибку протокола (Protocol Error), и в спецификации указан Reason Code, то он ДОЛЖЕН закрыть сетевое соединение.
[MQTT-4.13.2-1] Пакетам CONNACK и DISCONNECT дозволяется содержать Reason Code 0x80 или больше, чтобы показать, что сетевое соединение будет закрыто. Если указан Reason Code 0x80 или больше, то сетевое соединение ДОЛЖНО быть закрыто независимо от того, отправлены ли пакеты CONNACK или DISCONNECT.
[MQTT-6.0.0-1] MQTT Control Packets ДОЛЖЕН быть отправлен в кадрах двоичных данных WebSocket. Если принят любой другой тип кадра данных, то получатель ДОЛЖЕН закрыть сетевое соединение.
[MQTT-6.0.0-2] Один кадр данных WebSocket может содержать в себе несколько пакетов или часть пакета (MQTT Control Packet). Получатель НЕ ДОЛЖЕН подразумевать, что пакеты MQTT (MQTT Control Packet) выровнены по границам кадра WebSocket.
[MQTT-6.0.0-3] Клиент ДОЛЖЕН подключить "mqtt" в предоставляемый им список субпротоколов WebSocket.
[MQTT-6.0.0-4] Имя WebSocket Subprotocol, выбранное и возвращенное Сервером, ДОЛЖНО быть "mqtt".

В протокол MQTT v5.0 были добавлены следующие функции.

Session expiry (истечение времени жизни сессии). Флаг Clean Session разделен на флаг Clean Start, который показывает, что сессия должна начинаться без использования существующей сессии, и на интервал истечения времени жизни сессии (Session Expiry Interval), который указывает, как долго должна храниться сессия после разъединения. Session expiry interval может быть изменен в момент отключения. Установка Clean Start в 1 и Session Expiry Interval в 0 эквивалентно установке Clean Session в 1 протокола MQTT v3.1.1.

Message expiry. Позволяет установить время жизни сообщения в момент его публикации.

Reason code для всех пакетов ACK. Поменялись все пакеты ответа, чтобы они содержали код причины (Reason Code). Это включает CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK, DISCONNECT и AUTH. Это позволяет вызывающему определить, была ли выполнена запрошенная функция.

Reason String для всех пакетов ACK. Поменялись все пакеты с Reason Code, чтобы они опционально могли содержать строку описания причины (Reason String). Это было разработано для целей отладки проблем, и строка описания причины не должна обрабатываться Сервером.

Server disconnect. Позволяет Серверу послать пакет DISCONNECT, чтобы показать Клиенту причину закрытия соединения.

Формат полезной нагрузки и тип содержимого (content type). Позволяет указывать формат полезной нагрузки (binary, text) и содержимое типа MIME, когда публикуется сообщение. Эта информация перенаправляется получателю сообщения.

Request / Response. Формализованы шаблоны запрос/ответ MQTT, и предоставлены свойства темы ответа (Response Topic) и данных корреляции (Correlation Data), что позволяет направлять ответные сообщения обратно публикатору запроса. Также добавлена возможность получения Клиентом информации конфигурации Сервера о построении разделов тем ответов.

Shared Subscriptions (общие подписки). Добавлена возможность общей подписки, чтобы реализовать балансировку нагрузки потребителей подписки.

Subscription ID. Позволяет использовать цифровой идентификатор подписки, указанный в пакете SUBSCRIBE, возвращаемый в сообщении, когда оно доставлено. Это позволяет Клиенту определить, какая подписка (или подписки) привела к доставке сообщения.

Topic Alias (псевдоним темы). Позволяет уменьшать размер пакета MQTT путем замены имени темы небольшим цифровым идентификатором. Клиент и Сервер независимо друг от друга указывают, сколько псевдонимов имен они позволяют ввести.

Flow control (управление потоком). Позволяют Клиенту и Серверу независимо указать поддерживаемое количество оставшихся надежно передаваемых сообщений (QoS >0 ). Отправитель приостанавливает отправку таких сообщений, оставаясь в пределах указанной квоты. Это используется для ограничения частоты передачи надежных сообщений, а также для ограничения количества одновременно доставляемых сообщений.

User Properties (свойства пользователя). Для большинства пакетов добавлены свойства пользователя (User Properties). Свойства пользователя пакета PUBLISH включены в сообщение, и определяется приложениями Клиента. Свойства пользователя PUBLISH и Will Properties перенаправляются Сервером получателю сообщения. Свойства пользователя в пакетах CONNECT, SUBSCRIBE и UNSUBSCRIBE определены реализацией Сервера. Свойства пользователя пакетов CONNACK, PUBACK, PUBREC, PUBREL, PUBCOMP, SUBACK, UNSUBACK и AUTH определяются отправителем, и они уникальны для реализации Сервера. Это означает, что содержимое свойств пользователя и их интерпретация не определены протоколом MQTT.

Maximum Packet Size. Позволяют Клиенту и Серверу независимо указать поддерживаемый ими максимальный размер пакета. Ошибка партнера сессии, когда он посылает пакет большего размера.

Доступность дополнительного функционала Сервера. Определяется набор функций, который Сервер не разрешает, и предоставляется механизм для доставки этой информации Клиенту. Функции, которые могут быть указаны таким способом: Maximum QoS, Retain Available, Wildcard Subscription Available, Subscription Identifier Available и Shared Subscription Available. Будет ошибкой для Клиента использовать функции, которые Сервером были декларированы как недоступные.

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

Enhanced authentication (расширенная аутентификация). Предоставляется механизм для разрешения аутентификации стиля challenge/response, включая взаимную аутентификацию. Это позволяет использовать аутентификацию стиля SASL, если это поддерживается и Клиентом, и Сервером, и включает возможность для Клиента выполнить на соединении повторную аутентификацию.

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

Will delay. Добавлена возможность указать задержку между завершением соединения и отправкой will message. Это разработано таким образом, что если соединение для сессии восстановлено, то will message не посылается. Это позволяет кратковременно прерывать соединение без уведомления других пользователей.

Server Keep Alive. Позволяет Серверу указать значение, которое Клиент должен использовать для поддержания своей активности. Это позволяет Серверу указать максимально возможное время активности (keep alive) для Клиента, который должен его соблюдать.

Assigned ClientID. В случаях, когда идентификатор Клиента (ClientID) назначается Сервером, возвратит назначенный ClientID. Это также снимает ограничение на то, что назначенные Сервером идентификаторы Клиента могут использоваться только с подключениями Clean Session = 1.

Server reference (ссылка на Сервер). Позволяет Серверу в пакетах CONNACK или DISCONNECT указать Клиенту альтернативный Сервер для использования. Это может применяться для перенаправления или конфигурирования.

[Ссылки]

1. MQTT Specifications site:mqtt.org.
2. Библиотека ESP-MQTT.
3. Порядок следования байт (endianness).

 

Добавить комментарий


Защитный код
Обновить

Top of Page