WebSocket üzerinden MQTT, bir web sayfasının arada bir backend aktarıcısı olmadan doğrudan tarayıcıdan bir MQTT broker'a yayın yapmasını ve abone olmasını sağlar. Bu eğitimde tarayıcıların neden WebSocket taşımasına ihtiyaç duyduğunu, ws ile wss arasındaki farkı ve broker.connectmq.com ile konuşan eksiksiz bir HTML sayfası ile bir Node.js client'ının nasıl geliştirileceğini öğreneceksiniz.
Broker'lara yeni misiniz? Publish/subscribe temelleri için önce MQTT Broker Nedir? yazısını okuyun.
Tarayıcılar Neden WebSocket Üzerinden MQTT'ye İhtiyaç Duyar?
Yerel MQTT, genellikle 1883 portunda (TLS ile 8883'te) düz bir TCP bağlantısı üzerinden çalışır. Masaüstü uygulamaları, sunucular ve mikrodenetleyiciler TCP soketlerini serbestçe açabilir. Tarayıcılar açamaz: güvenlik nedeniyle bir web sayfasındaki JavaScript yalnızca HTTP, WebSocket ve tarayıcının yönettiği birkaç başka taşımaya erişebilir.
WebSocket bu sorunu çözer. Upgrade: websocket başlığına sahip sıradan bir HTTP isteği olarak başlar ve sunucu 101 Switching Protocols yanıtını verdiğinde bağlantı tam çift yönlü (full-duplex) bir ikili kanala dönüşür. MQTT paketleri (CONNECT, PUBLISH, SUBSCRIBE vb.) bundan sonra WebSocket frame'leri içinde değiştirilmeden taşınır. Client, broker'ın ne bekleyeceğini bilmesi için el sıkışma sırasında mqtt alt protokolünü talep eder.
Browser (MQTT.js) broker.connectmq.com:8084
|-- TLS handshake ------------------------------>|
|-- GET /mqtt Upgrade: websocket |
| Sec-WebSocket-Protocol: mqtt ---------------->|
|<-- 101 Switching Protocols ---------------------|
|== WebSocket frame [ MQTT CONNECT ] ============>|
|<= WebSocket frame [ MQTT CONNACK ] =============|
|== WebSocket frame [ MQTT SUBSCRIBE ] ==========>|
|<= WebSocket frame [ MQTT PUBLISH ] =============|
Broker açısından bir WebSocket client'ı sıradan bir MQTT client'ıdır. TCP üzerinden bağlı cihazlarla konuşabilir, onlarla topic paylaşabilir ve aynı QoS seviyelerini, retained message'ları ve MQTT 5 özelliklerini kullanabilir.
WebSocket üzerinden MQTT'nin tipik kullanım alanları:
- Bir sensör yayın yaptığı anda güncellenen canlı IoT dashboard'ları
- Cihazlara komut gönderen tarayıcı tabanlı kontrol panelleri
- Makine durumunu gerçek zamanlı görselleştiren izleme araçları ve dijital ikizler
- Web teknolojileriyle geliştirilmiş hibrit mobil uygulamalar
ws ve wss: ConnectMQ'da Portlar ve Yollar
HTTP ve HTTPS gibi WebSocket'in de şifresiz (ws://) ve TLS ile şifreli (wss://) biçimleri vardır.
| Taşıma | Şema | Port | Tam URL | Ne zaman kullanılır |
|---|---|---|---|---|
| MQTT (TCP) | mqtt:// | 1883 | mqtt://broker.connectmq.com:1883 | Cihazlar, sunucular, CLI |
| TLS üzerinden MQTT | mqtts:// | 8883 | mqtts://broker.connectmq.com:8883 | Üretimdeki cihazlar ve sunucular |
| WebSocket | ws:// | 8083 | ws://broker.connectmq.com:8083/mqtt | http:// sayfasından yerel testler |
| Güvenli WebSocket | wss:// | 8084 | wss://broker.connectmq.com:8084/mqtt | Tarayıcılar ve üretimdeki web uygulamaları |
İki ayrıntı önemlidir:
- Yol
/mqtt'dir. WebSocket URL'si bir HTTP URL'sidir, dolayısıyla bir yolu vardır./mqttolmadanwss://broker.connectmq.com:8084adresine bağlanmak el sıkışmanın başarısız olmasına yol açar. - wss'yi tercih edin. HTTPS üzerinden sunulan sayfalar yalnızca
wss://bağlantıları açabilir ve düzws://üzerinden gönderilen kimlik bilgileri açık metin olarak taşınır. ConnectMQ, 8084'te WSS'yi Let's Encrypt sertifikasıyla sunar; bu yüzden tarayıcılar ek ayar gerektirmeden ona güvenir.
MQTT.js ile WebSocket Üzerinden MQTT Sayfası Geliştirin
Aşağıdaki sayfa eksiksiz ve kendi kendine yeterlidir. index.html olarak kaydedin ve bir tarayıcıda açın. MQTT.js'i bir CDN'den yükler, broker.connectmq.com'un public alanına anonim olarak bağlanır, benzersiz bir topic'e abone olur ve mesaj yayınlamanıza izin verir.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>MQTT over WebSocket demo</title>
<script src="https://unpkg.com/mqtt@5.10.3/dist/mqtt.min.js"></script>
</head>
<body>
<p>Status: <span id="status">connecting...</span></p>
<input id="msg" value="Hello from the browser">
<button id="send">Publish</button>
<pre id="log"></pre>
<script>
const id = Math.random().toString(16).slice(2, 10);
const clientId = "web-" + id;
const topic = "connectmq/demo/" + id + "/chat";
const log = (line) => {
document.getElementById("log").textContent += line + "\n";
};
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
clientId: clientId,
protocolVersion: 5,
clean: true,
keepalive: 30,
reconnectPeriod: 2000,
connectTimeout: 10000
});
client.on("connect", () => {
document.getElementById("status").textContent = "connected as " + clientId;
client.subscribe(topic, { qos: 1 }, (err, granted) => {
if (err) return log("Subscribe error: " + err.message);
log("Subscribed to " + granted[0].topic + " (QoS " + granted[0].qos + ")");
});
});
client.on("message", (t, payload) => {
log("[" + t + "] " + payload.toString());
});
client.on("reconnect", () => {
document.getElementById("status").textContent = "reconnecting...";
});
client.on("error", (err) => log("Error: " + err.message));
document.getElementById("send").onclick = () => {
const text = document.getElementById("msg").value;
client.publish(topic, text, { qos: 1 });
};
</script>
</body>
</html>
Publish düğmesine tıkladığınızda mesaj güvenli WebSocket üzerinden broker'a gider ve kendi aboneliğiniz üzerinden doğrudan geri gelir. Sayfayı iki sekmede açarsanız her sekmenin kendi rastgele topic'ini aldığını, dolayısıyla birbirlerini görmediklerini fark edersiniz. Bir topic'i paylaşmak için her ikisine de aynı connectmq/demo/<your-id>/chat topic'ini sabit olarak yazın.
Seçenekler hakkında birkaç not:
clientIdboş olmamalı ve benzersiz olmalıdır. Public alan boş client ID'yi reddeder; aynı ID'ye sahip iki client ise sürekli birbirini düşürür.protocolVersion: 5MQTT 5 kullanır. Gerekirse MQTT 3.1.1 için4kullanın.keepalive: 30, bağlantı boştayken client'ın bir PINGREQ göndermesini sağlar; böylece broker ve aradaki proxy'ler bağlantının hâlâ canlı olduğunu bilir.reconnectPeriod: 2000, MQTT.js'in bir kopmadan iki saniye sonra otomatik olarak yeniden bağlanmasını sağlar.
TCP ve WebSocket client'ları aynı topic'leri paylaştığı için tarayıcının mesajlarını Mosquitto CLI ile bir terminalden de izleyebilirsiniz. abc12345 yerine sayfadaki topic'te görünen id'yi yazın:
mosquitto_sub -h broker.connectmq.com -p 1883 -i cli-watch-abc12345 -t "connectmq/demo/abc12345/#" -v
Node.js'te WebSocket Üzerinden MQTT
Node.js düz TCP kullanabilir; ancak sunucunuz yalnızca HTTPS benzeri trafiğe izin veren bir proxy veya güvenlik duvarının arkasındaysa ya da kodu bir tarayıcı uygulamasıyla paylaşmak istiyorsanız WebSocket kullanışlıdır. MQTT.js'i npm install mqtt ile kurun ve şunu ws-client.mjs olarak kaydedin:
import mqtt from "mqtt";
const id = Math.random().toString(16).slice(2, 10);
const clientId = `node-${id}`;
const topic = `connectmq/demo/${id}/hello`;
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
clientId,
protocolVersion: 5,
keepalive: 30,
});
client.on("connect", (connack) => {
console.log("Connected, CONNACK properties:", connack.properties);
client.subscribe(topic, { qos: 1 }, (err, granted) => {
if (err) throw err;
console.log("Granted:", granted);
client.publish(topic, JSON.stringify({ temp: 21.5, ts: Date.now() }), { qos: 1 });
});
});
client.on("message", (t, payload) => {
console.log(`Received on ${t}: ${payload.toString()}`);
client.end();
});
client.on("error", (err) => {
console.error("Connection error:", err.message);
client.end();
});
node ws-client.mjs ile çalıştırın. Çıktı buna benzer:
Connected, CONNACK properties: { receiveMaximum: 16, topicAliasMaximum: 65535 }
Granted: [ { topic: 'connectmq/demo/4df8521c/hello', qos: 1, nl: false, rap: false, rh: 0 } ]
Received on connectmq/demo/4df8521c/hello: {"temp":21.5,"ts":1790000000000}
Bir TCP client'ından tek farkı URL'dir. Onu mqtt://broker.connectmq.com:1883 ile değiştirin; kodun geri kalanı aynı kalır. Yukarıdaki qos değerlerini anlamak istiyorsanız MQTT QoS Seviyeleri yazısına bakın.
WebSocket Üzerinden MQTT Bağlantı Sorunlarını Giderme
Sorunların çoğu, hiçbir zaman connect aşamasına ulaşmayan veya sürekli yeniden bağlanan bir bağlantı olarak ortaya çıkar. Tarayıcının geliştirici araçlarını açın, Console ve Network sekmesini (WS ile filtreleyerek) kontrol edin ve bu tabloyla karşılaştırın.
| Belirti | Olası neden | Çözüm |
|---|---|---|
| "Mixed Content" hatası, bağlantı engellendi | Bir https:// sayfası ws:// açmaya çalışıyor | wss://broker.connectmq.com:8084/mqtt kullanın |
| El sıkışma başarısız, Network sekmesinde HTTP 404 | Yol eksik veya yanlış | URL'ye /mqtt ekleyin |
| 8083 veya 8084'te el sıkışma başarısız | Şema ve port karışmış (8084'te ws, 8083'te wss) | ws 8083 ile, wss 8084 ile kullanılır |
| Bir CORS sorunu olduğundan şüpheleniyorsunuz | WebSocket, fetch/XHR gibi CORS'a tabi değildir | Gerçek nedeni arayın: URL, port, TLS veya kimlik bilgileri |
| Bağlanıyor, sonra birkaç saniyede bir kopuyor | İki client aynı client ID'yi kullanıyor | Her sekme veya cihaz için benzersiz ID üretin |
| CONNECT'ten hemen sonra bağlantı reddediliyor | Boş client ID veya yanlış kullanıcı adı/parola | Boş olmayan bir client ID ayarlayın; portal kimlik bilgilerini kontrol edin |
| Bir süre işlem yapılmayınca kopuyor | Keepalive, proxy veya mobil ağ için fazla uzun | keepalive: 30 veya daha düşük kullanın |
| Yerelde çalışıyor, kurumsal ağda başarısız | Proxy veya güvenlik duvarı standart dışı portları engelliyor | Başka bir ağdan test edin veya BT'den 8084 portuna giden trafiğe izin vermesini isteyin |
Bunlardan ikisi daha yakından bakmayı hak ediyor.
Mixed content (karışık içerik)
Tarayıcılar güvenli sayfalarda güvensiz alt kaynakları engeller. Dashboard'unuz https:// üzerinden sunuluyorsa herhangi bir ws:// bağlantısı tarayıcıdan çıkmadan reddedilir ve broker onu hiç görmez. Çözüm her zaman wss://'dir. Şifresiz ws://broker.connectmq.com:8083/mqtt uç noktası yalnızca http://localhost üzerinden veya yerel bir dosyadan açılan sayfalar için işe yarar.
Client ID çakışmaları
MQTT, client ID başına yalnızca bir bağlantıya izin verir. Aynı ID ile ikinci bir bağlantı geldiğinde broker ilkini kapatır. Tarayıcıda bu durum genellikle bir kullanıcı aynı sayfayı iki sekmede açtığında ve client ID sabit kodlandığında yaşanır. Otomatik yeniden bağlanma açıksa iki sekme ID için sonsuza dek kavga eder. Her sekmeye rastgele bir sonek ekleyin. Özel bir ConnectMQ broker'da client ID'ler verilen client ID ve onun _suffix varyantlarıyla sınırlıdır; bu yüzden YOUR_CLIENT_ID_tab1, YOUR_CLIENT_ID_tab2 gibi değerler kullanın.
Üretim: Portaldan Alınan Kimlik Bilgilerini Kullanmak
Public alan test içindir: orada yayınlanan her şey herkes tarafından okunabilir ve sıkı limitleri vardır (mesaj başına 64 KB, client başına saniyede 10 mesaj). Gerçek bir uygulama için portalda özel bir broker oluşturun ve üretilen kimlik bilgileriyle bağlanın:
const client = mqtt.connect("wss://broker.connectmq.com:8084/mqtt", {
clientId: "YOUR_CLIENT_ID_dashboard",
username: "YOUR_USERNAME",
password: "YOUR_PASSWORD",
protocolVersion: 5,
keepalive: 30,
});
Tarayıcı uygulamaları için şu noktaları aklınızda tutun:
- Üretimde her zaman wss kullanın. Kullanıcı adı ve parola CONNECT paketinde gönderilir, bu yüzden taşıma şifreli olmalıdır.
- Tarayıcıdaki kimlik bilgilerini görünür kabul edin. Tarayıcıya gönderilen her şey kullanıcısı tarafından okunabilir. Cihaz kimlik bilgilerini yeniden kullanmak yerine web uygulamasına kendi kimlik bilgilerini verin ve bunları herkese açık sayfalara gömmekten kaçının.
- Plan limitlerine uyun. Açık her sekme bir bağlantıdır. Serverless (Free) planı en fazla 25 eşzamanlı bağlantıya izin verir; bu prototipler için uygundur. Üretim dashboard'ları en fazla 1.000 bağlantı sunan Serverless (Paid) planına veya bir Dedicated kümeye daha iyi oturur.
- Yeniden bağlanmaları zarifçe ele alın. Bir durum göstergesi sunun ve bağlantı geri geldiğinde yeniden abone olun ya da kalıcı bir oturuma güvenin.
Daha fazla sağlamlaştırma önerisi MQTT Güvenliği: En İyi Uygulamalar yazısında toplanmıştır.
ConnectMQ ile Başlayın
WebSocket üzerinden MQTT'yi wss://broker.connectmq.com:8084/mqtt public uç noktasıyla hemen test edebilirsiniz. Gerçek bir dashboard geliştirmeye hazır olduğunuzda app.connectmq.com adresinden ücretsiz kaydolun (ücretsiz Serverless planı, kredi kartı gerekmez), bir broker oluşturun ve kendi kullanıcı adınız, parolanız ve client ID'nizle bağlanın. Portaldaki yerleşik tarayıcı MQTT client'ı ve canlı topic gezgini, web uygulamanızın beklediğiniz şeyi yayınlayıp yayınlamadığını kontrol etmeyi kolaylaştırır.
Sık Sorulan Sorular
WebSocket üzerinden MQTT hangi portu kullanır?
Tek bir standart port yoktur. broker.connectmq.com üzerinde şifresiz WebSocket 8083 portunu, güvenli WebSocket ise 8084 portunu kullanır; her ikisi de /mqtt yoluyla.
WebSocket üzerinden MQTT, TCP üzerinden MQTT'den daha mı yavaştır?
Ek yük küçüktür. Tek seferlik HTTP yükseltmesinden sonra her MQTT paketi yalnızca birkaç bayt ekleyen bir WebSocket frame'ine sarılır; bu yüzden çoğu uygulama için gecikme düz TCP'ye yakındır.
Tarayıcıda MQTT kullanmak için bir backend sunucusuna ihtiyacım var mı?
Hayır. WebSocket üzerinden MQTT ile tarayıcı doğrudan broker'a bağlanır. Backend'e yalnızca kimlik bilgilerini client dışında tutmak veya kendi iş mantığınızı eklemek istiyorsanız ihtiyaç duyarsınız.
CORS, WebSocket üzerinden MQTT için geçerli mi?
Hayır. WebSocket bağlantıları, fetch ve XHR istekleri gibi CORS preflight kontrollerine tabi değildir. Bir bağlantı başarısız olursa bunun yerine URL'yi, portu, yolu ve kimlik bilgilerini kontrol edin.
Tarayıcı client'ları ve ESP32 cihazları aynı topic'leri paylaşabilir mi?
Evet. Broker, mesajları taşıma türünden bağımsız olarak topic'e göre yönlendirir; dolayısıyla WSS üzerindeki bir tarayıcı ile TCP 1883 portundaki bir cihaz aynı topic'lere yayın yapıp abone olabilir. Cihaz tarafı için ESP32 MQTT eğitimine bakın.



