MQTT nasıl çalışır? Kısaca: Client'lar bir broker'a uzun ömürlü tek bir bağlantı açar, hangi topic'lerle ilgilendiklerini bildirir ve broker yayınlanan her mesajı eşleşen abonelere iletir. Bu yazıda bu süreci TCP bağlantısından CONNECT, SUBSCRIBE, PUBLISH, keep alive ve bağlantı kesmeye kadar paket paket takip edecek ve tüm izi genel bir broker üzerinde kendiniz yeniden oluşturacaksınız.
Üç Rol: Yayıncı, Abone ve Broker
MQTT'de yalnızca iki tür katılımcı vardır: client'lar ve broker'lar. Bir client yayın yapabilir, abone olabilir ya da ikisini birden yapabilir. Broker ortada durur, her mesajı alır ve kimin alacağına karar verir.
- Yayıncılar (publisher) mesajları
plant1/line2/temperaturegibi bir dize olan bir topic'e gönderir. Mesajı kimin aldığını bilmez ve önemsemezler. - Aboneler (subscriber) broker'a hangi topic'leri veya topic desenlerini istediklerini söyler. Kimin gönderdiğini bilmezler.
- Broker client'ların kimliğini doğrular, abonelikleri ve oturumları takip eder ve her mesajı eşleşen tüm abonelere yönlendirir.
Bu ayrıştırma tasarımın kalbidir. Bir sensörün bir dashboard'un IP adresini bilmesine gerek yoktur; oturumlar kalıcıysa ikisinin aynı anda çevrimiçi olması gerekmez ve beşinci bir tüketici eklemek sensörde hiçbir değişiklik gerektirmez. Broker'ın görevi hakkında daha fazlası için bir MQTT broker'ın ne yaptığı yazısına, desenin kendisi için ise MQTT yayınla/abone ol modeli yazısına bakın.
Adım 1: Ağ Bağlantısını Açmak
MQTT güvenilir ve sıralı bir bayt akışı üzerinde, normalde TCP üzerinde çalışır. Client broker'a bir TCP bağlantısı açar: düz MQTT için 1883, TLS üzerinden MQTT için 8883 portunda. Ham TCP soketi açamayan tarayıcılar ise MQTT'yi bir WebSocket içinde taşır (ConnectMQ'da /mqtt yoluyla 8083 veya 8084). Henüz MQTT'ye özgü hiçbir şey olmadı; bu sadece borunun kendisidir.
TLS kullanılıyorsa bu noktada bir el sıkışma gerçekleşir: Client broker'ın sertifikasını kontrol eder ve iki taraf şifreleme anahtarlarında anlaşır. Sonraki her MQTT paketi şifrelidir.
Adım 2: CONNECT ve CONNACK
Client'ın ilk paketi CONNECT olmak zorundadır. Şunları taşır:
| Alan | Amaç |
|---|---|
| Protokol adı ve seviyesi | MQTT ve 4 (3.1.1) veya 5 (5.0) |
| Client ID | Oturumu tanımlar; her bağlantı için benzersiz olmalıdır |
| Clean session / clean start | Sıfırdan başla veya kayıtlı bir oturumu sürdür |
| Keep alive | Client'tan gelen paketler arasındaki azami saniye |
| Kullanıcı adı ve parola | İsteğe bağlı kimlik bilgileri |
| Last Will | Client kaybolursa broker'ın yayınlayacağı isteğe bağlı mesaj |
| Özellikler (MQTT 5) | Oturum süresi, receive maximum, azami paket boyutu ve daha fazlası |
Broker tüm bunları doğrular ve CONNACK ile yanıt verir. MQTT 5'te bu yanıt bir reason code içerir: Başarı için 0x00 ya da hatalı kimlik bilgileri, yetkisiz erişim veya kota sınırlı bir broker'da 0x97 quota exceeded gibi bir hata. Ayrıca önceki bir oturumun sürdürülüp sürdürülmediğini (session present bayrağı) belirtir ve client'a sunucu sınırlarını bildirebilir. Başarılı bir CONNACK gelene kadar client başka hiçbir şey göndermemelidir.
Adım 3: SUBSCRIBE ve SUBACK
Mesaj almak isteyen bir client, bir veya daha fazla topic filtresi ve her biri için talep edilen QoS ile SUBSCRIBE gönderir. Filtreler joker karakter içerebilir: + tam olarak bir seviyeyle, # ise bir seviyenin altındaki her şeyle eşleşir. Örneğin plant1/+/temperature, plant1/line2/temperature ile eşleşir ancak plant1/line2/motor/temperature ile eşleşmez.
Broker, filtre başına verilen QoS'u (veya bir hata kodunu) listeleyen SUBACK ile yanıt verir. Broker sınır koyuyorsa verilen QoS talep edilenden düşük olabilir. Eşleşen topic'lerde retained message varsa broker bunları hemen gönderir; yeni bir dashboard mevcut durumu bu sayede anında öğrenir.
Adım 4: PUBLISH ve QoS El Sıkışmaları
Veri göndermek için client bir topic adı, bir payload (herhangi bir bayt dizisi, çoğunlukla JSON), bir QoS seviyesi ve bir retain bayrağıyla PUBLISH gönderir. Sonrasında olacaklar QoS'a bağlıdır:
- QoS 0, en fazla bir kez. PUBLISH ve bitti. Onay yoktur; bağlantı yanlış anda koparsa mesaj kaybolur.
- QoS 1, en az bir kez. Alıcı PUBACK ile yanıt verir. Gönderen bunu almazsa duplicate bayrağı ayarlanmış olarak yeniden gönderir; bu yüzden alıcı mesajı iki kez görebilir.
- QoS 2, tam olarak bir kez. Dört adımlı bir alışveriş: PUBLISH, PUBREC, PUBREL, PUBCOMP. Daha yavaş ama yineleme yok.
Bu el sıkışmalar atlama atlama (hop by hop) gerçekleşir: bir kez yayıncı ile broker arasında, ayrıca broker ile her abone arasında ayrı ayrı. Broker ardından mesajı, filtresi eşleşen her client'a, yayın QoS'u ile aboneliğe verilen QoS'tan düşük olanı kullanarak iletir. Tüm ödünleşimler MQTT QoS seviyeleri açıklaması yazısında.
Retain bayrağı ayarlanmışsa broker mesajı o topic için bilinen son değer olarak da saklar ve gelecekteki abonelere verir.
Adım 5: PINGREQ ve PINGRESP ile Keep Alive
Boşta olsa bile client, keep alive aralığı içinde hayatta olduğunu kanıtlamalıdır. Yayınlayacak bir şeyi yoksa PINGREQ gönderir ve broker PINGRESP ile yanıt verir. Broker keep alive süresinin yaklaşık bir buçuk katı boyunca hiçbir şey duymazsa client'ı ölü kabul eder, bağlantıyı kapatır ve ayarlanmışsa client'ın Last Will mesajını yayınlar. Dashboard'lar bir cihazın çevrimdışı olduğunu kimse sorgulama (polling) yapmadan bu şekilde öğrenir.
Adım 6: DISCONNECT ve Oturumlar
Temiz bir kapanış DISCONNECT gönderir; bu da broker'a Last Will'i yayınlamamasını söyler. Neyin kalıcı olacağı oturum ayarlarına bağlıdır: Clean start ile ve oturum süresi olmadan broker client'ın aboneliklerini unutur. Kalıcı bir oturumla (MQTT 5'te sıfırdan büyük oturum süresi) broker abonelikleri saklar ve client geri dönene ya da süre dolana kadar QoS 1 ve 2 mesajlarını kuyruğa alır.
İzi Kendiniz Yeniden Oluşturun
Tüm yaşam döngüsünü broker.connectmq.com adresindeki ücretsiz genel MQTT broker üzerinde izleyebilirsiniz. Mosquitto'nun client'ları -d ile her paketi yazdırır. Önce benzersiz, rastgele bir kimlik seçin; burada q7m3x9.
# Terminal 1: hata ayıklama çıktılı abone
mosquitto_sub -h broker.connectmq.com -p 1883 -i sub-q7m3x9 -V mqttv5 -d \
-t 'connectmq/demo/q7m3x9/#' -q 1
# Terminal 2: hata ayıklama çıktılı yayıncı
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
Abonenin çıktısı şuna benzer (ayrıntılar sürüme göre değişir):
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
Yayıncınınki ise:
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
PUBLISH satırındaki bayrakları okuyun: d0 (yineleme değil), q1 (QoS 1), r0 (retained değil), m1 (paket tanımlayıcısı 1). -q 2 deneyin, PUBREC, PUBREL ve PUBCOMP'u göreceksiniz; yayıncıya -r ekleyin, aboneyi yeniden başlatın ve retained message SUBACK'ten hemen sonra gelir. Genel alanı herkes okuyabilir, bu yüzden yalnızca test verisi gönderin.
Aynı Akış Python'da
Kütüphaneler paketleri callback'lerin arkasına gizler, ancak her biri yukarıdaki bir adıma karşılık gelir.
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): # gelen PUBLISH
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()
Yaygın Yanlış Anlamalar
- "Broker tüm mesajları saklar." Yalnızca retained message'ları (topic başına bir tane) ve kalıcı oturumlar için kuyruğa alınmış mesajları saklar. MQTT bir veritabanı veya log değildir.
- "Topic'lerin önce oluşturulması gerekir." Hayır, topic'ler biri yayın yaptığı veya abone olduğu anda var olur.
- "Uçtan uca QoS 2." QoS atlama başına uygulanır ve aboneliğin seviyesine düşürülür.
- "Client ID'ler paylaşılabilir." Aynı kimlikle yapılan ikinci bir bağlantı ilkini düşürür.
- "MQTT UDP kullanır." Standart MQTT TCP'ye veya başka bir güvenilir akışa ihtiyaç duyar; UDP ve benzeri ağlar için olan varyant MQTT-SN'dir.
Daha ileri gitmek için MQTT eğitimi eksiksiz bir proje kurar, MQTT kontrol paketleri her paket türünü ayrıntılandırır ve resmi spesifikasyonlar mqtt.org adresinde yayımlanmıştır.
MQTT'yi ConnectMQ'da Deneyin
broker.connectmq.com üzerinde özgürce deney yapın, ardından özel ve kimliği doğrulanmış topic'ler istediğinizde app.connectmq.com adresinde kredi kartı gerektirmeden ücretsiz bir Serverless broker oluşturun. ConnectMQ, tarayıcı içi client'ı ve canlı topic gezgini ile MQTT 3.1.1 ve 5.0'ı destekleyen bir bulut MQTT broker olduğundan burada anlatılan akışları gerçek zamanlı izleyebilirsiniz. Üretime geçtiğinizde ise tam yönetilen bir MQTT hizmeti olarak çalışır.
Sık Sorulan Sorular
MQTT basitçe nasıl çalışır?
Cihazlar merkezi bir broker'a bağlanır, ilgilendikleri topic'lere abone olur ve topic'lere mesaj yayınlar. Broker her mesajı eşleşen tüm abonelere iletir.
Yayıncılar ve aboneler birbirine doğrudan bağlanır mı?
Hayır. Her client yalnızca broker'a bağlanır; cihazların birbirinin adresine hiç ihtiyaç duymamasının nedeni budur.
Bir mesaj yayınlandığında abone çevrimdışıysa ne olur?
Kalıcı bir oturum ve QoS 1 veya 2 ile broker, abone yeniden bağlanana veya oturum süresi dolana kadar mesajı kuyruğa alır. Aksi halde mesaj o client'a teslim edilmez; yine de bir retained message ona en son değeri verir.
MQTT hangi portu kullanır?
Düz TCP için 1883, TLS için 8883. WebSocket portları broker'a göre değişir; ConnectMQ /mqtt yoluyla 8083 ve 8084'ü kullanır.



