Bir MQTT bağlantısı dört katmanda başarısız olabilir: ağ (DNS ve TCP), aktarım (TLS veya WebSocket), MQTT el sıkışması (CONNECT / CONNACK) ve canlı oturum (keep-alive ve bağlantı kesilmeleri). Katmanı belirlemek çözümün yarısıdır. Bu rehber, karşılaşmanız muhtemel hata mesajları ve reason code’larıyla birlikte her katmanı tek tek ele alıyor.
Hızlı ön teşhis
| Belirti | Katman | En olası neden |
|---|---|---|
ENOTFOUND / getaddrinfo hatası | DNS | Host adında yazım hatası veya host alanına URL şemasının eklenmesi |
| Takılıyor, sonra zaman aşımına uğruyor | Ağ | Portu düşüren bir firewall, yanlış port veya tarayıcıdan TCP portu kullanımı |
ECONNREFUSED | Ağ | O host ve portta dinleyen bir şey yok |
| Sertifika veya el sıkışma hatası | TLS | Güvenilmeyen CA, host adı uyuşmazlığı veya düz bir porta TLS ile bağlanma |
| Bağlandıktan hemen sonra bağlantı kapanıyor | MQTT | Hata kodlu CONNACK — aşağıdaki tablolara bakın |
| Bağlanıyor, sonra tekrar tekrar kopuyor | Oturum | Aynı client ID’nin iki kez kullanılması veya keep-alive yapılandırma hatası |
Bağlantı zaman aşımları
Zaman aşımı, paketlerinizin gittiği ama hiçbir şeyin geri gelmediği anlamına gelir. Broker’ın hayır deme fırsatı bile olmamıştır. Sırasıyla şunları kontrol edin:
- Port aktarımla eşleşiyor mu? 1883’te
mqtt://, 8883’temqtts://, broker’ın WebSocket portundawss://. Bkz. MQTT portları. - Ağınız porta izin veriyor mu? Kurumsal ve misafir ağlar genellikle 1883 ve 8883’ü engeller. Doğrulamak için 443 üzerinde
wss://deneyin. - Broker çalışıyor mu? Genel test ortamları haber vermeden yeniden başlar; kendi kurulumunuzu olasılık dışı bırakmak için başka bir broker’ı test edin.
- Sunucu firewall’ınız açık mı? Kendi barındırdığınız broker’larda bulut security group’u listener portuna gelen trafiğe izin vermelidir.
ECONNREFUSED
ECONNREFUSED, işletim sisteminden gelen hızlı ve açık bir reddir: host’a erişilebilir, ancak o portta dinleyen bir süreç yoktur. Tipik nedenler; çalışmayan bir broker, yalnızca 127.0.0.1’e bağlanmış bir listener, hiç publish edilmemiş bir container portu (docker run -p 1883:1883) veya broker başka bir container’dayken bir container’ın içinden localhost’a bağlanmaktır.
TLS hataları
- Kendinden imzalı veya bilinmeyen CA (
SELF_SIGNED_CERT_IN_CHAIN,UNABLE_TO_VERIFY_LEAF_SIGNATURE): client’a CA dosyasını verin. Yerel testler dışında doğrulamayı kapatmayın. - Host adı uyuşmazlığı (
ERR_TLS_CERT_ALTNAME_INVALID): IP adresi veya dahili bir takma ad yerine sertifikadaki adla bağlanın. - Wrong version number / packet length too long: düz metin bir porta TLS (örneğin 1883’te
mqtts://) ya da TLS portuna düz MQTT konuşuyorsunuz. - Süresi dolmuş sertifika: tarihleri
openssl s_client -connect host:8883 -servername hostile kontrol edin.
Yalnızca tarayıcıda görülen hatalar: mixed content ve WebSocket path’leri
Tarayıcılar MQTT’yi yalnızca WebSocket üzerinden kullanabilir ve kendi kurallarını ekler. HTTPS üzerinden sunulan bir sayfa ws:// açamaz — tarayıcı daha hiçbir paket gönderilmeden bunu mixed content olarak engeller ve hata yalnızca geliştirici konsolunda görünür. wss:// kullanın. Diğer sık hata eksik path’tir: birçok broker /mqtt bekler ve o olmadan WebSocket upgrade’i 404 ile başarısız olur. Daha fazlası için WebSocket üzerinden MQTT yazısını okuyun.
Çalıştığı bilinen bir wss bağlantısını test edin
MQTT 3.1.1 CONNACK return code’ları
Ağ ve aktarım çalışıyorsa broker CONNECT’e CONNACK ile yanıt verir. MQTT 3.1.1’de bu paket bir baytlık bir return code taşır:
| Kod | Anlamı | Ne düzeltilmeli |
|---|---|---|
0 | Connection accepted (bağlantı kabul edildi) | Hiçbir şey — bağlısınız |
1 | Unacceptable protocol version (kabul edilemeyen protokol sürümü) | Broker istenen sürümü desteklemiyor; MQTT 3.1.1 ile 5 arasında geçiş yapın |
2 | Identifier rejected (tanımlayıcı reddedildi) | Client ID geçersiz, çok uzun, izin verilmediği halde boş veya engellenmiş |
3 | Server unavailable (sunucu kullanılamıyor) | Broker aşırı yüklü veya bakımda; backoff ile yeniden deneyin |
4 | Bad user name or password (hatalı kullanıcı adı veya parola) | Kimlik bilgilerini ve kodlamalarını kontrol edin |
5 | Not authorized (yetkisiz) | Hesabın bağlanma izni yok; broker ACL’lerini veya client ID kuralını kontrol edin |
Yaygın MQTT 5 reason code’ları
MQTT 5, return code’ların yerine reason code’ları kullanır. 0x80 ve üzerindeki her değer bir hatadır. Aynı kodlar CONNACK içinde veya sunucunun gönderdiği bir DISCONNECT içinde görülebilir:
| Kod | Ad | Tipik neden |
|---|---|---|
0x80 | Unspecified error | Genel hata; broker log’larını kontrol edin |
0x84 | Unsupported Protocol Version | Broker yalnızca 3.1.1 konuşuyor |
0x85 | Client Identifier not valid | Hatalı biçimli veya izin verilmeyen client ID |
0x86 | Bad User Name or Password | Yanlış kimlik bilgileri |
0x87 | Not authorized | Bağlanma izni olmayan geçerli kullanıcı |
0x88 | Server unavailable | Broker şu anda bağlantı kabul edemiyor |
0x8A | Banned | Client veya IP, operatör tarafından engellenmiş |
0x8C | Bad authentication method | Enhanced auth yöntemi desteklenmiyor |
0x95 | Packet too large | CONNECT, broker’ın maksimum paket boyutunu aşıyor |
0x97 | Quota exceeded | Hesap bir bağlantı veya kullanım sınırına ulaştı |
0x9F | Connection rate exceeded | Çok hızlı yeniden bağlanılıyor; backoff ekleyin |
Bir oturum sırasında DISCONNECT paketlerinde iki kod daha görülür: 0x8D (Keep Alive timeout) ve 0x8E (Session taken over). İkisi de aşağıda ele alınıyor. MQTT 5’in neleri değiştirdiğine dair genel tablo için MQTT 5 ve 3.1.1 yazısına bakın.
Client ID devralma döngüleri
Spesifikasyon, aynı client ID ile yeni bir bağlantı geldiğinde broker’ın mevcut client’ın bağlantısını kesmesini şart koşar. İki cihaz — ya da iki tarayıcı sekmesi — bir ID’yi paylaşıyor ve ikisi de otomatik yeniden bağlanıyorsa birkaç saniyede bir sırayla birbirlerini düşürürler. MQTT 5’te kaybeden taraf 0x8E içeren bir DISCONNECT alır; 3.1.1’de ise soket basitçe kapanır.
Keep-alive kaynaklı bağlantı kopmaları
CONNECT içindeki keep-alive değeri broker’a ne sıklıkla trafik bekleyeceğini söyler. Broker bu aralığın bir buçuk katı boyunca hiçbir şey görmezse bağlantıyı kapatır. Client’lar boştayken PINGREQ gönderir, ancak bloklanmış bir event loop, uyuyan bir cihaz veya agresif bir NAT ya da load balancer boşta kalma zaman aşımı yine de bağlantıyı koparabilir. Aralığı ağınızın boşta kalma zaman aşımının altında tutun (60 saniye yaygın bir varsayılandır) ve MQTT client’ına hizmet eden thread’i asla bloklamayın.
Gerçek hatayı log’layın
Çoğu kütüphane, siz dinlemedikçe nedeni gizler. MQTT.js ile:
import mqtt from 'mqtt';
const client = mqtt.connect('wss://broker.emqx.io:8084/mqtt', {
protocolVersion: 5,
clientId: `debug-${Math.random().toString(16).slice(2, 10)}`,
reconnectPeriod: 5000,
});
client.on('connect', (connack) => console.log('connected', connack.reasonCode ?? 0));
client.on('error', (err) => console.error('error:', err.message, err.code));
client.on('disconnect', (packet) => console.warn('server disconnect, reason', packet.reasonCode));
client.on('close', () => console.warn('socket closed'));Kontrol listesi
- Çalıştığı bilinen bir genel broker’da gidiş-dönüşü online client ile doğrulayın.
- Şemayı, portu ve path’i broker’ın belgelenmiş listener’ıyla eşleştirin.
- Tahmin etmek yerine CONNACK kodunu veya reason code’u okuyun.
- Benzersiz bir client ID kullanın ve backoff ile yeniden bağlanın.
- Keep-alive’ı yol üzerindeki tüm boşta kalma zaman aşımlarından kısa tutun.
Eksiksiz bir test prosedürü için MQTT broker nasıl test edilir yazısını izleyin.
Sıkça sorulan sorular
MQTT “connection refused: not authorized” ne anlama gelir?
Broker ağ bağlantısını kabul etmiş ancak client’ı reddetmiştir. MQTT 3.1.1’de bu CONNACK return code 5, MQTT 5’te ise reason code 0x87’dir. Kimlik bilgileri geçerli olabilir, ancak hesabın bağlanmasına veya o client ID’yi kullanmasına izin verilmiyordur.
MQTT client’ım neden sürekli bağlantıyı kesip yeniden bağlanıyor?
En yaygın neden, iki client’ın aynı client ID’yi kullanmasıdır. Broker, bu ID ile her yeni bağlantı geldiğinde eski oturumun bağlantısını keser; ikisi de otomatik yeniden bağlanıyorsa bir döngü içinde birbirlerini düşürürler. Her client’a benzersiz bir ID verin.
MQTT bağlantım neden hata vermek yerine zaman aşımına uğruyor?
Zaman aşımı hiç yanıt gelmediği anlamına gelir; bu da genellikle paketleri sessizce düşüren bir firewall’a, yanlış bir host’a veya tarayıcıdan TCP portunun kullanılmasına işaret eder. Ret ise bir şeyin yanıt verip hayır dediği anlamına gelir.