Tarayıcıda JavaScript ile MQTT çalıştırmak, backend yazmadan canlı bir pano, uzaktan kumanda paneli veya hata ayıklama aracı geliştirmenin en hızlı yoludur. Bu eğitimde güvenli WebSocket üzerinden broker.connectmq.com adresine bağlanan, bir topic'e abone olan, mesaj yayınlayan ve bunları gerçek zamanlı gösteren, kendi kendine yeten tek bir HTML sayfası oluşturacaksınız. Ayrıca tarayıcıların MQTT için neden WebSocket'e ihtiyaç duyduğunu, CORS'un neden sorun olmadığını ve aynı sayfayı private bir broker'a nasıl güvenle taşıyacağınızı da öğreneceksiniz.
Tarayıcı Neden WebSocket Üzerinden MQTT'ye İhtiyaç Duyar?
Bir web sayfası ham TCP soketi açamaz. Tarayıcı sandbox'ı JavaScript'in ağla yalnızca HTTP(S), WebSocket, WebRTC ve birkaç yeni API üzerinden konuşmasına izin verir. Standart MQTT, 1883 portunda TCP (veya 8883'te TLS) üzerinden çalışır; bu yüzden bir tarayıcı bu portlara doğrudan ulaşamaz.
MQTT spesifikasyonu bunu, MQTT paketlerinin WebSocket ikili çerçeveleri içinde taşınmasına izin vererek çözer. Broker ek bir dinleyici sunar, tarayıcı ona bir WebSocket açar ve bundan sonra iletişim sıradan MQTT'dir: CONNECT, SUBSCRIBE, PUBLISH, PINGREQ. Protokol düzeyindeki ayrıntıları istiyorsanız WebSocket üzerinden MQTT rehberimiz el sıkışmayı ve alt protokol başlığını adım adım anlatır.
ConnectMQ her broker'da iki WebSocket dinleyicisi sunar:
| Uç nokta | URL | Ne zaman kullanılır |
|---|---|---|
| WebSocket | ws://broker.connectmq.com:8083/mqtt |
Yalnızca bir http:// sayfasından yerel test |
| Güvenli WebSocket | wss://broker.connectmq.com:8084/mqtt |
https:// üzerinden sunulan her sayfa ve tüm üretim kullanımı |
Varsayılan olarak wss:// kullanın. HTTPS üzerinden yüklenen bir sayfanın şifrelenmemiş bir ws:// bağlantısı açmasına izin verilmez; tarayıcı bunu, makineden tek bir paket çıkmadan karma içerik (mixed content) olarak engeller.
Peki ya CORS?
CORS (Cross-Origin Resource Sharing) fetch ve XMLHttpRequest için geçerlidir. WebSocket bağlantıları CORS preflight kontrollerine tabi değildir. Tarayıcı yükseltme (upgrade) sırasında bir Origin başlığı gönderir ve sunucu bunu incelemeyi seçebilir, ancak Access-Control-Allow-Origin dansı yoktur. Bu yüzden aşağıdaki HTML dosyasını masaüstünüzden, yerel bir geliştirme sunucusundan veya herhangi bir alan adından açabilirsiniz; proxy hilelerine gerek kalmadan bağlanır.
Kütüphane Seçimi: MQTT.js
MQTT.js, JavaScript için fiili standart MQTT client'ıdır. Aynı paket Node.js'te ve tarayıcılarda çalışır, MQTT 3.1.1 ve MQTT 5'i destekler; yeniden bağlanma, keepalive ve QoS 1 ile 2 akışlarını sizin için yönetir. Sürüm 5 önceden derlenmiş bir tarayıcı paketiyle gelir; böylece onu tek bir script etiketiyle bir CDN'den yükleyebilirsiniz. GitHub'daki MQTT.js dokümantasyonu tüm seçenekleri listeler; minimal bir client'ın ihtiyacı olan tek şey aşağıdaki alt kümedir.
Daha sonra bir bundler'a veya framework'e geçerseniz kod neredeyse hiç değişmez. Node.js ile MQTT.js rehberimiz sunucu tarafını ele alır, React MQTT eğitimi ise aynı client'ın hook'lar içine nasıl sarılacağını gösterir.
Eksiksiz Tek Sayfalık Tarayıcı MQTT JavaScript Client'ı
Aşağıdakini mqtt-client.html olarak kaydedin ve herhangi bir modern tarayıcıda açın. MQTT.js'i bir CDN'den yükler, benzersiz bir client ID ve rastgele bir topic öneki üretir ve size bağlanma, abone olma ve yayın yapma düğmeleri sunar.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Minimal MQTT Browser Client</title>
<script src="https://unpkg.com/mqtt@5.10.1/dist/mqtt.min.js"></script>
<style>
body { font-family: system-ui, sans-serif; max-width: 720px; margin: 2rem auto; padding: 0 1rem; }
input, button { font: inherit; padding: .4rem .6rem; }
#log { border: 1px solid #ccc; height: 280px; overflow-y: auto; padding: .5rem; font-family: monospace; font-size: .85rem; }
.row { display: flex; gap: .5rem; margin: .5rem 0; }
.row input { flex: 1; }
</style>
</head>
<body>
<h1>MQTT in the Browser</h1>
<p>Status: <strong id="status">disconnected</strong></p>
<div class="row">
<input id="url" value="wss://broker.connectmq.com:8084/mqtt">
<button id="connectBtn">Connect</button>
<button id="disconnectBtn">Disconnect</button>
</div>
<div class="row">
<input id="subTopic">
<button id="subBtn">Subscribe</button>
</div>
<div class="row">
<input id="pubTopic">
<input id="pubPayload" value='{"temperature": 21.5}'>
<button id="pubBtn">Publish</button>
</div>
<div id="log"></div>
<script>
const randomId = Math.random().toString(16).slice(2, 10);
const prefix = `connectmq/demo/${randomId}`;
document.getElementById("subTopic").value = `${prefix}/#`;
document.getElementById("pubTopic").value = `${prefix}/sensors/room1`;
const statusEl = document.getElementById("status");
const logEl = document.getElementById("log");
let client = null;
function log(text) {
const line = document.createElement("div");
line.textContent = `[${new Date().toLocaleTimeString()}] ${text}`;
logEl.appendChild(line);
logEl.scrollTop = logEl.scrollHeight;
}
document.getElementById("connectBtn").onclick = () => {
if (client) return;
const url = document.getElementById("url").value;
client = mqtt.connect(url, {
clientId: `browser-${randomId}`,
protocolVersion: 5,
clean: true,
keepalive: 30,
connectTimeout: 10000,
reconnectPeriod: 3000
// Private bir ConnectMQ broker için şunları ekleyin:
// username: "YOUR_USERNAME",
// password: "YOUR_PASSWORD"
});
client.on("connect", () => { statusEl.textContent = "connected"; log(`Connected to ${url}`); });
client.on("reconnect", () => { statusEl.textContent = "reconnecting"; });
client.on("close", () => { statusEl.textContent = "disconnected"; });
client.on("offline", () => log("Client went offline"));
client.on("error", (err) => log(`Error: ${err.message}`));
client.on("message", (topic, payload, packet) => {
const retained = packet.retain ? " (retained)" : "";
log(`${topic}${retained}: ${payload.toString()}`);
});
};
document.getElementById("disconnectBtn").onclick = () => {
if (!client) return;
client.end(false, () => log("Disconnected cleanly"));
client = null;
};
document.getElementById("subBtn").onclick = () => {
if (!client) return log("Connect first");
const topic = document.getElementById("subTopic").value;
client.subscribe(topic, { qos: 1 }, (err, granted) => {
if (err) return log(`Subscribe failed: ${err.message}`);
granted.forEach(g => log(`Subscribed to ${g.topic} (granted QoS ${g.qos})`));
});
};
document.getElementById("pubBtn").onclick = () => {
if (!client) return log("Connect first");
const topic = document.getElementById("pubTopic").value;
const payload = document.getElementById("pubPayload").value;
client.publish(topic, payload, { qos: 1 }, (err) => {
if (err) log(`Publish failed: ${err.message}`);
});
};
</script>
</body>
</html>
Önce Connect'e, sonra Subscribe'a, ardından Publish'e tıklayın. Mesaj sayfanızdan broker'a gider ve doğrudan aynı sayfaya geri döner, çünkü yayın topic'iyle eşleşen prefix/# filtresine abonesiniz.
Kod Nasıl Çalışır?
Bağlanma
mqtt.connect() hemen bir client döndürür ve arka planda bağlanır. Sonrasında ne olduğunu olaylar söyler: başarılı bir CONNACK'ten sonra connect, her yeniden denemede reconnect, soket kapandığında close ve reddedilen bir oturum açma gibi sorunlar için error. protocolVersion: 5 ayarı size reason code'lar ve user property'ler gibi MQTT 5 özelliklerini sağlar; 3.1.1'e dönmek için kaldırın.
Client ID her sayfa yüklemesinde üretilir. Public broker boş olmayan herhangi bir client ID'yi kabul eder, ancak aynı ID'ye sahip iki client bir döngü içinde birbirini bağlantıdan atar; bu da sürekli kopan bir bağlantı gibi görünür. Rastgele ID'ler, sayfayı iki sekmede açtığınızda bunu önler.
Abone olma ve mesaj alma
message olayı gelen her PUBLISH için tetiklenir. payload bir bayt tamponudur; metin için toString(), JSON için JSON.parse(payload.toString()) çağırın. Üçüncü argüman retain, qos ve MQTT 5 altında properties alanlarını sunan ham pakettir.
log fonksiyonunda textContent kullanıldığına dikkat edin. Broker'ın public alanına herkes yayın yapabilir; bu yüzden her payload'ı güvenilmeyen girdi olarak ele alın. Onu innerHTML ile eklemek, kötü niyetli bir mesajın sayfanızda script çalıştırmasına izin verirdi.
Yayın yapma
client.publish(topic, payload, options, callback) mesajı kuyruğa alır. QoS 1 ile callback, broker mesajı PUBACK ile onayladıktan sonra çalışır. Bağlantı kopuksa MQTT.js, sayfa açık kaldığı sürece QoS 1 ve 2 mesajlarını giden deposunda tutar ve yeniden bağlandıktan sonra gönderir. QoS seviyeleri rehberi bu garantinin ne zaman önemli olduğunu açıklar.
Diğer Taraftan Test Etmek
Mesajların gerçekten broker'dan geçtiğini kanıtlamak için sayfada Publish'e tıklarken onları bir terminalden izleyin. Öneki sayfanızın gösterdiğiyle değiştirin:
mosquitto_sub -h broker.connectmq.com -p 1883 -i cli-watch-7f3a -t 'connectmq/demo/YOUR_PREFIX/#' -v
Terminalden yayın yapın, tarayıcı logu anında güncellenir:
mosquitto_pub -h broker.connectmq.com -p 1883 -i cli-pub-7f3a -t 'connectmq/demo/YOUR_PREFIX/sensors/room1' -m '{"temperature": 23.1}'
Tarayıcıdan TCP client'ına ve geri dönen bu gidiş-dönüş, bir WebSocket client'ı ile yerel bir TCP client'ının broker'da aynı topic alanını paylaştığının en açık kanıtıdır.
Sorun Giderme Kontrol Listesi
Durum hiçbir zaman "connected" olmuyorsa bu listeyi sırayla izleyin:
- Yanlış yol. ConnectMQ, WebSocket'i
/mqttyolunda sunar. Yolu olmayan bir URL HTTP yükseltmesi sırasında başarısız olur. - Karma içerik. Bir
https://sayfasıws://açamaz. 8084 portundawss://kullanın. - Port engellenmiş. Bazı kurumsal ağlar yalnızca 443'e izin verir. Bunu elemek için başka bir ağdan veya telefonunuzun hotspot'undan test edin.
- Yinelenen client ID. Log'da connect ve close birkaç saniyede bir tekrarlanıyorsa başka bir client aynı ID'yi kullanıyor demektir.
- Boş veya geçersiz kimlik bilgileri. Private bir broker'da hatalı bir kullanıcı adı veya parola "Not authorized" ya da "Bad username or password" içeren bir
errorolayı üretir. Portaldaki değerleri kontrol edin. - Public broker sınırları. Public broker client başına saniyede 10 mesaja, client başına 10 aboneliğe, mesaj başına 64 KB'a ve 8 topic seviyesine izin verir. Hızlı bir döngüye bağlanmış bir düğme hız sınırına takılır.
- DevTools. Network sekmesini açın, WS'ye göre filtreleyin ve çerçeveleri inceleyin. İkili MQTT paketlerini ve yükseltme yanıt kodunu görürsünüz.
Public Broker'dan Private Bir Broker'a Geçiş
Public broker bu eğitim için mükemmeldir, ancak public alanındaki her topic, onu tahmin eden herkes tarafından okunabilir. Gerçek projeler için kendi broker'ınızı oluşturun:
- app.connectmq.com adresinden kaydolun ve ücretsiz Serverless planını seçin.
- Bir broker oluşturun ve üretilen kullanıcı adını, parolayı ve client ID'yi kopyalayın.
- URL'yi broker'ınızın 8084 portundaki
/mqttyollu güvenli WebSocket uç noktasıyla değiştirin ve seçeneklerdeusername,passwordveclientIddeğerlerini ayarlayın.
Bu kimlik bilgilerinin nerede durduğuna dikkat edin. Tarayıcı JavaScript'ine koyduğunuz her şey DevTools'u açan herkes tarafından okunabilir. İyi modeller şunlardır:
- Tarayıcı panoları için cihazlarınızın kullandıklarını değil, ayrı ve düşük yetkili kimlik bilgileri kullanın.
- Kimlik bilgilerini sayfaya gömmek yerine kullanıcıdan çalışma zamanında girmesini isteyin.
- Herkese açık siteler için yetki gerektiren yayınları bir backend'e bırakın ve tarayıcıyı salt okunur tutun. Next.js MQTT modelleri yazısı bu ayrımı gösterir.
MQTT güvenliği için en iyi uygulamalar rehberi kimlik bilgisi yönetimi ve topic tasarımı konularına daha derinlemesine girer.
Bundan Sonra Ne Yapmalı?
Bu tek sayfa, birkaç yönde büyütebileceğiniz bir temeldir:
- Canlı grafikler. JSON payload'larını ayrıştırın ve değerleri bir grafik kütüphanesine gönderin. Uzun oturumlarda belleğin sabit kalması için sabit uzunlukta bir dizi tutun.
- Sohbet ve çevrimiçi durumu. Retained message'lar ve Last Will, kimin çevrimiçi olduğunu göstermeyi kolaylaştırır. MQTT sohbet uygulaması eğitimi tam olarak bunu oluşturur.
- Tipli kod. Sayfa büyürse TypeScript'e ve bir bundler'a geçin; TypeScript ile MQTT rehberi payload'ların ve olayların tiplendirilmesini ele alır.
- Diğer diller. Backend'iniz farklı bir teknoloji yığını kullanıyorsa MQTT client kütüphanelerine genel bakış MQTT.js'i Python, Go, Java ve C# client'larıyla karşılaştırır.
ConnectMQ ile Başlayın
ConnectMQ, 8084 portunda güvenli WebSocket'i önceden yapılandırılmış, Let's Encrypt sertifikalı ve sayfanızın ne yayınladığını kontrol etmek için portalda tarayıcı içi bir MQTT client'ı ile canlı topic gezgini sunan, tamamen yönetilen bir MQTT broker sağlar. Bugün public MQTT test broker ile başlayın, hazır olduğunuzda private bir bulut MQTT broker oluşturun. Kredi kartı gerektirmeyen Serverless planında ücretsiz bir hesap oluşturun.
Sık Sorulan Sorular
Bir tarayıcı 1883 portunda MQTT'ye bağlanabilir mi?
Hayır. Tarayıcılar ham TCP bağlantıları açamaz, bu yüzden WebSocket üzerinden MQTT kullanmaları gerekir. ConnectMQ'da bu, her ikisi de /mqtt yolunda olmak üzere ws:// için 8083, wss:// için 8084 portudur.
Tarayıcıda MQTT kullanmak için bir backend'e veya proxy'ye ihtiyacım var mı?
Hayır. Sayfa broker'a doğrudan WebSocket üzerinden bağlanır ve WebSocket CORS preflight'a tabi değildir. Bir backend yalnızca yetkili kimlik bilgilerini client'tan uzak tutmak istediğinizde faydalıdır.
Tarayıcılar için tek JavaScript MQTT kütüphanesi MQTT.js mi?
MQTT 5 desteği ve hazır bir tarayıcı paketiyle en yaygın kullanılan ve aktif olarak bakımı yapılan seçenektir. Eski Paho JavaScript client'ı hâlâ çalışır, ancak yeni projeler için artık yaygın tercih değildir.
Tarayıcı client'ım neden birkaç saniyede bir yeniden bağlanıyor?
En yaygın neden, aynı client ID'yi paylaşan iki client'tır; bu da broker'ın her seferinde eskisinin bağlantısını kesmesine yol açar. Sekme başına rastgele bir ID üretin ve public broker'ın hız sınırlarını aşmadığınızdan da emin olun.



