Fondamentaux MQTT

Comment fonctionne MQTT ? Brokers, clients et messages expliqués

Une explication pas à pas du fonctionnement de MQTT, de l'ouverture d'une connexion TCP à CONNECT, SUBSCRIBE, PUBLISH, au keep alive et à la déconnexion, avec une trace reproductible sur le serveur MQTT public gratuit.

Schéma expliquant comment fonctionne MQTT, avec des clients qui envoient des paquets CONNECT, SUBSCRIBE et PUBLISH via un broker central
Essayez-le sur votre propre broker MQTTObtenez un broker MQTT privé et managé avec l’offre Free et partez d’exemples de code prêts à l’emploi.
Essayer gratuitement Exemples de code Aucune carte bancaire requise

Comment fonctionne MQTT ? En bref, les clients ouvrent une connexion de longue durée vers un broker, déclarent les topics qui les intéressent, et le broker transmet chaque message publié aux abonnés correspondants. Dans cet article, vous allez suivre ce processus paquet par paquet, de la connexion TCP à CONNECT, SUBSCRIBE, PUBLISH, au keep alive et à la déconnexion, et reproduire vous-même toute la trace sur le serveur MQTT public gratuit.

Les trois rôles : publisher, subscriber et broker

MQTT ne compte que deux types de participants : les clients et les brokers. Un client peut publier, s'abonner, ou les deux. Le broker se trouve au milieu, reçoit chaque message et décide qui le reçoit.

  • Les publishers envoient des messages sur un topic, une chaîne comme plant1/line2/temperature. Ils ne savent pas qui les reçoit et ne s'en soucient pas.
  • Les subscribers indiquent au broker quels topics, ou quels motifs de topics, ils veulent recevoir. Ils ne savent pas qui envoie.
  • Le broker authentifie les clients, suit les abonnements et les sessions, et achemine chaque message vers tous les abonnés correspondants.

Ce découplage est au cœur de la conception. Un capteur n'a pas besoin de l'adresse IP d'un tableau de bord, les deux n'ont pas besoin d'être en ligne au même moment si les sessions sont persistantes, et ajouter un cinquième consommateur ne demande aucune modification du capteur. Pour en savoir plus sur le rôle du broker, voir ce que fait un broker MQTT, et pour le modèle lui-même, le modèle publication/abonnement de MQTT.

Étape 1 : ouvrir une connexion réseau

MQTT fonctionne sur un flux d'octets fiable et ordonné, normalement TCP. Le client ouvre une connexion TCP vers le broker, sur le port 1883 pour MQTT en clair ou 8883 pour MQTT sur TLS. Les navigateurs, qui ne peuvent pas ouvrir de sockets TCP bruts, transportent MQTT dans un WebSocket (sur ConnectMQ, 8083 ou 8084 avec le chemin /mqtt). Rien de spécifique à MQTT ne s'est encore produit ; ce n'est que le tuyau.

Avec TLS, une négociation a alors lieu : le client vérifie le certificat du broker et les deux parties s'accordent sur les clés de chiffrement. Tous les paquets MQTT suivants sont chiffrés.

Étape 2 : CONNECT et CONNACK

Le premier paquet du client doit être CONNECT. Il contient :

Champ Rôle
Nom et niveau du protocole MQTT et 4 (3.1.1) ou 5 (5.0)
Client ID Identifie la session ; doit être unique par connexion
Clean session / clean start Repartir de zéro ou reprendre une session enregistrée
Keep alive Nombre maximal de secondes entre deux paquets du client
Nom d'utilisateur et mot de passe Identifiants facultatifs
Last Will Message facultatif que le broker publie si le client disparaît
Propriétés (MQTT 5) Expiration de session, receive maximum, taille maximale des paquets, etc.

Le broker valide tout cela et répond par CONNACK. En MQTT 5, ce paquet contient un reason code : 0x00 en cas de succès, ou une erreur comme des identifiants incorrects, une absence d'autorisation ou, sur un broker soumis à des quotas, 0x97 quota exceeded. Il indique aussi si une session précédente a été reprise (drapeau session present) et peut informer le client des limites du serveur. Tant qu'un CONNACK de succès n'est pas arrivé, le client ne doit rien envoyer d'autre.

Étape 3 : SUBSCRIBE et SUBACK

Un client qui veut recevoir des messages envoie SUBSCRIBE avec un ou plusieurs filtres de topic et une QoS demandée pour chacun. Les filtres peuvent contenir des wildcards : + correspond à exactement un niveau et # à tout ce qui se trouve sous un niveau. Par exemple, plant1/+/temperature correspond à plant1/line2/temperature mais pas à plant1/line2/motor/temperature.

Le broker répond par SUBACK, en indiquant la QoS accordée (ou un code d'échec) pour chaque filtre. La QoS accordée peut être inférieure à celle demandée si le broker la plafonne. S'il existe des retained messages sur des topics correspondants, le broker les envoie immédiatement : c'est ainsi qu'un nouveau tableau de bord connaît instantanément l'état courant.

Étape 4 : PUBLISH et les échanges de QoS

Pour envoyer des données, un client envoie PUBLISH avec un nom de topic, un payload (n'importe quels octets, souvent du JSON), un niveau de QoS et un drapeau retain. La suite dépend de la QoS :

  1. QoS 0, au plus une fois. PUBLISH, et c'est tout. Aucun acquittement ; si la connexion tombe au mauvais moment, le message est perdu.
  2. QoS 1, au moins une fois. Le destinataire répond par PUBACK. Si l'émetteur ne le reçoit pas, il renvoie le message avec le drapeau duplicate positionné : le destinataire peut donc voir le message deux fois.
  3. QoS 2, exactement une fois. Un échange en quatre temps : PUBLISH, PUBREC, PUBREL, PUBCOMP. Plus lent, mais sans doublons.

Ces échanges ont lieu saut par saut : une fois entre le publisher et le broker, et séparément entre le broker et chaque subscriber. Le broker transmet ensuite le message à chaque client dont le filtre correspond, en utilisant la plus basse des deux QoS, celle de la publication ou celle accordée à l'abonnement. Tous les compromis sont détaillés dans les niveaux de QoS MQTT expliqués.

Si le drapeau retain est positionné, le broker stocke aussi le message comme dernière valeur connue pour ce topic et le remet aux futurs abonnés.

Étape 5 : le keep alive avec PINGREQ et PINGRESP

Même inactif, un client doit prouver qu'il est vivant dans l'intervalle de keep alive. S'il n'a rien à publier, il envoie PINGREQ et le broker répond PINGRESP. Si le broker n'entend rien pendant environ une fois et demie la période de keep alive, il considère le client comme mort, ferme la connexion et publie le Last Will du client, s'il en a défini un. C'est ainsi que les tableaux de bord apprennent qu'un appareil est passé hors ligne sans que personne n'ait à interroger.

Étape 6 : DISCONNECT et sessions

Un arrêt propre envoie DISCONNECT, qui indique au broker de ne pas publier le Last Will. Ce qui survit dépend des paramètres de session : avec clean start et sans expiration de session, le broker oublie les abonnements du client. Avec une session persistante (expiration de session MQTT 5 supérieure à zéro), le broker conserve les abonnements et met en file les messages QoS 1 et 2 jusqu'au retour du client ou jusqu'à l'expiration.

Reproduisez la trace vous-même

Vous pouvez observer tout le cycle de vie sur le serveur MQTT public gratuit, broker.connectmq.com. Les clients Mosquitto affichent chaque paquet avec -d. Choisissez d'abord un identifiant aléatoire unique ; ici, c'est q7m3x9.

# Terminal 1 : abonné avec sortie de débogage
mosquitto_sub -h broker.connectmq.com -p 1883 -i sub-q7m3x9 -V mqttv5 -d \
  -t 'connectmq/demo/q7m3x9/#' -q 1

# Terminal 2 : publisher avec sortie de débogage
mosquitto_pub -h broker.connectmq.com -p 1883 -i pub-q7m3x9 -V mqttv5 -d \
  -t 'connectmq/demo/q7m3x9/sensor/temp' -m '{"c":21.7}' -q 1

La sortie de l'abonné ressemble à ceci (les détails varient selon la version) :

Client sub-q7m3x9 sending CONNECT
Client sub-q7m3x9 received CONNACK (0)
Client sub-q7m3x9 sending SUBSCRIBE (Mid: 1, Topic: connectmq/demo/q7m3x9/#, QoS: 1, Options: 0x00)
Client sub-q7m3x9 received SUBACK
Subscribed (mid: 1): 1
Client sub-q7m3x9 received PUBLISH (d0, q1, r0, m1, 'connectmq/demo/q7m3x9/sensor/temp', ... (10 bytes))
Client sub-q7m3x9 sending PUBACK (m1, rc0)
{"c":21.7}
Client sub-q7m3x9 sending PINGREQ
Client sub-q7m3x9 received PINGRESP

Et celle du publisher :

Client pub-q7m3x9 sending CONNECT
Client pub-q7m3x9 received CONNACK (0)
Client pub-q7m3x9 sending PUBLISH (d0, q1, r0, m1, 'connectmq/demo/q7m3x9/sensor/temp', ... (10 bytes))
Client pub-q7m3x9 received PUBACK (Mid: 1, RC:0)
Client pub-q7m3x9 sending DISCONNECT

Lisez les drapeaux de la ligne PUBLISH : d0 (pas un doublon), q1 (QoS 1), r0 (non retained), m1 (identifiant de paquet 1). Essayez -q 2 et vous verrez PUBREC, PUBREL et PUBCOMP ; ajoutez -r au publisher, redémarrez l'abonné, et le retained message arrive immédiatement après SUBACK. L'espace public est lisible par n'importe qui : n'envoyez que des données de test.

Le même flux en Python

Les bibliothèques cachent les paquets derrière des callbacks, mais chacun correspond à une étape ci-dessus.

import time
import uuid

import paho.mqtt.client as mqtt

PREFIX = f"connectmq/demo/{uuid.uuid4().hex[:6]}"


def on_connect(client, userdata, flags, reason_code, properties):   # CONNACK
    print("CONNACK:", reason_code)
    client.subscribe(f"{PREFIX}/#", qos=1)                           # SUBSCRIBE


def on_subscribe(client, userdata, mid, reason_codes, properties):  # SUBACK
    print("SUBACK:", [str(rc) for rc in reason_codes])
    client.publish(f"{PREFIX}/sensor/temp", '{"c":21.7}', qos=1)     # PUBLISH


def on_publish(client, userdata, mid, reason_code, properties):     # PUBACK
    print("PUBACK for mid", mid)


def on_message(client, userdata, msg):                               # PUBLISH entrant
    print("Message:", msg.topic, msg.payload.decode())


client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2,
                     client_id=f"trace-{uuid.uuid4().hex[:8]}",
                     protocol=mqtt.MQTTv5)
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_publish = on_publish
client.on_message = on_message

client.connect("broker.connectmq.com", 1883, keepalive=30)          # TCP + CONNECT
client.loop_start()
time.sleep(5)
client.disconnect()                                                  # DISCONNECT
client.loop_stop()

Les idées reçues courantes

  • « Le broker stocke tous les messages. » Seulement les retained messages (un par topic) et les messages en file pour les sessions persistantes. MQTT n'est ni une base de données ni un journal.
  • « Les topics doivent être créés au préalable. » Non, les topics existent dès que quelqu'un publie ou s'abonne.
  • « La QoS 2 de bout en bout. » La QoS s'applique saut par saut et est abaissée au niveau de l'abonnement.
  • « Les client ID peuvent être partagés. » Une seconde connexion avec le même ID éjecte la première.
  • « MQTT utilise UDP. » MQTT standard nécessite TCP ou un autre flux fiable ; MQTT-SN est la variante pour UDP et les réseaux similaires.

Pour aller plus loin, le tutoriel MQTT construit un projet complet, les paquets de contrôle MQTT détaille chaque type de paquet, et les spécifications officielles sont publiées sur mqtt.org.

Essayez MQTT sur ConnectMQ

Expérimentez librement sur broker.connectmq.com, puis créez un broker Serverless (Free) sur app.connectmq.com, sans carte bancaire, quand vous voulez des topics privés et authentifiés. ConnectMQ est un broker MQTT cloud qui prend en charge MQTT 3.1.1 et 5.0, avec un client intégré au navigateur et un explorateur de topics en direct pour observer en temps réel les flux décrits ici. Quand vous passez en production, il fonctionne comme un broker MQTT managé.

Questions fréquentes

Comment fonctionne MQTT en termes simples ?

Les appareils se connectent à un broker central, s'abonnent aux topics qui les intéressent et publient des messages sur des topics. Le broker transmet chaque message à tous les abonnés correspondants.

Les publishers et les subscribers se connectent-ils directement entre eux ?

Non. Chaque client se connecte uniquement au broker, c'est pourquoi les appareils n'ont jamais besoin de connaître leurs adresses respectives.

Que se passe-t-il si un abonné est hors ligne au moment où un message est publié ?

Avec une session persistante et une QoS 1 ou 2, le broker met le message en file jusqu'à la reconnexion de l'abonné ou l'expiration de la session. Sinon, le message n'est pas livré à ce client, même si un retained message lui donnera toujours la dernière valeur.

Quel port MQTT utilise-t-il ?

1883 pour TCP en clair et 8883 pour TLS. Les ports WebSocket varient selon le broker ; ConnectMQ utilise 8083 et 8084 avec le chemin /mqtt.

Articles liés

Qui a inventé MQTT ? L'histoire, des oléoducs à l'IoT

MQTT a été inventé en 1999 par Andy Stanford-Clark (IBM) et Arlen Nipper (Arcom) pour surveiller des oléoducs par satellite. Suivez son parcours vers l'open source, OASIS, l'ISO et les brokers MQTT managés d'aujourd'hui.

8 min de lecture

Pourquoi votre client MQTT se déconnecte sans cesse (et comment y remédier)

Les boucles de reconnexion sont l'un des problèmes MQTT les plus courants. Découvrez les cinq causes habituelles, des client ID en double aux timeouts de keep alive et aux paquets trop volumineux, et suivez une méthode de diagnostic qui identifie la vôtre.

9 min de lecture

Taille maximale d'un message MQTT : limites et stratégies pour les gros payloads

MQTT peut techniquement transporter un paquet de 256 Mo, mais les brokers, les bibliothèques clientes et les appareils imposent des limites bien plus basses. Découvrez où se trouvent les vraies limites, ce qui se passe quand on les dépasse et comment envoyer de gros payloads.

8 min de lecture

Tous les articles →

Votre broker MQTT privé, à quelques clics

Créez un compte, récupérez les identifiants de votre broker et connectez votre premier appareil — aucun serveur à installer, mettre à jour ou dimensionner.