IoT-Tutorials

MQTT über WebSocket: Einen Browser mit MQTT.js an einen MQTT Broker anbinden

Browser können keine rohen TCP-Sockets öffnen, deshalb sprechen Web-Apps MQTT über WebSocket. Bauen Sie einen funktionierenden Browser-Client und einen Node.js-Client für broker.connectmq.com und lernen Sie, die häufigsten Verbindungsfehler zu beheben.

Browser-Dashboard, das sich über einen Secure WebSocket mit einem MQTT Broker verbindet (MQTT über WebSocket)
Probieren Sie es auf Ihrem eigenen MQTT-Broker ausHolen Sie sich im Free-Tarif einen privaten, verwalteten MQTT-Broker und starten Sie mit fertigen Codebeispielen.
Kostenlos testen Codebeispiele Keine Kreditkarte erforderlich

Mit MQTT über WebSocket kann eine Webseite direkt aus dem Browser heraus auf einem MQTT Broker veröffentlichen und abonnieren – ohne Backend-Relais dazwischen. In diesem Tutorial erfahren Sie, warum Browser den WebSocket-Transport brauchen, worin sich ws und wss unterscheiden und wie Sie eine komplette HTML-Seite und einen Node.js-Client bauen, die mit broker.connectmq.com kommunizieren.

Neu bei Brokern? Lesen Sie zuerst Was ist ein MQTT Broker?, um die Grundlagen von Publish/Subscribe kennenzulernen.

Warum Browser MQTT über WebSocket brauchen

Natives MQTT läuft über eine einfache TCP-Verbindung, meist auf Port 1883 (oder 8883 mit TLS). Desktop-Apps, Server und Mikrocontroller können TCP-Sockets frei öffnen. Browser können das nicht: Aus Sicherheitsgründen stehen JavaScript in einer Webseite nur HTTP, WebSocket und einige weitere vom Browser verwaltete Transportwege zur Verfügung.

WebSocket löst dieses Problem. Die Verbindung beginnt als gewöhnliche HTTP-Anfrage mit dem Header Upgrade: websocket, und sobald der Server mit 101 Switching Protocols antwortet, wird daraus ein binärer Vollduplex-Kanal. MQTT-Pakete (CONNECT, PUBLISH, SUBSCRIBE usw.) werden dann unverändert in WebSocket-Frames transportiert. Der Client fordert beim Handshake das Subprotokoll mqtt an, damit der Broker weiß, was ihn erwartet.

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 ] =============|

Aus Sicht des Brokers ist ein WebSocket-Client einfach ein weiterer MQTT-Client. Er kann mit Geräten kommunizieren, die per TCP verbunden sind, Topics mit ihnen teilen und dieselben QoS-Stufen, Retained Messages und MQTT-5-Funktionen nutzen.

Typische Einsatzgebiete für MQTT über WebSocket:

  • Live-IoT-Dashboards, die sich in dem Moment aktualisieren, in dem ein Sensor veröffentlicht
  • Browserbasierte Bedienoberflächen, die Befehle an Geräte senden
  • Monitoring-Tools und digitale Zwillinge, die den Maschinenzustand in Echtzeit darstellen
  • Hybride mobile Apps auf Basis von Webtechnologien

In Industrie-4.0-Projekten abonniert ein solches Browser-Dashboard typischerweise einen Ausschnitt des Unified Namespace (UNS), etwa acme/werk-stuttgart/montage/#, dessen Topic-Struktur der ISA-95-Hierarchie aus Werk, Bereich, Linie und Zelle folgt.

ws vs. wss: Ports und Pfade bei ConnectMQ

Wie bei HTTP und HTTPS gibt es WebSocket in einer unverschlüsselten (ws://) und einer TLS-verschlüsselten (wss://) Variante.

Transport Schema Port Vollständige URL Einsatz
MQTT (TCP) mqtt:// 1883 mqtt://broker.connectmq.com:1883 Geräte, Server, CLI
MQTT über TLS mqtts:// 8883 mqtts://broker.connectmq.com:8883 Geräte und Server in der Produktion
WebSocket ws:// 8083 ws://broker.connectmq.com:8083/mqtt Lokale Tests von einer http://-Seite
Secure WebSocket wss:// 8084 wss://broker.connectmq.com:8084/mqtt Browser und produktive Web-Apps

Zwei Details sind wichtig:

  • Der Pfad lautet /mqtt. Eine WebSocket-URL ist eine HTTP-URL und hat daher einen Pfad. Eine Verbindung zu wss://broker.connectmq.com:8084 ohne /mqtt lässt den Handshake scheitern.
  • Bevorzugen Sie wss. Seiten, die über HTTPS ausgeliefert werden, dürfen nur wss://-Verbindungen öffnen, und Zugangsdaten über unverschlüsseltes ws:// werden im Klartext übertragen. ConnectMQ stellt WSS auf 8084 mit einem Let's-Encrypt-Zertifikat bereit, dem Browser ohne zusätzliche Einrichtung vertrauen.

Eine Seite für MQTT über WebSocket mit MQTT.js bauen

Die folgende Seite ist vollständig und eigenständig. Speichern Sie sie als index.html und öffnen Sie sie im Browser. Sie lädt MQTT.js von einem CDN, verbindet sich anonym mit dem öffentlichen Bereich von broker.connectmq.com, abonniert ein eindeutiges Topic und lässt Sie Nachrichten veröffentlichen.

<!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>

Wenn Sie auf Publish klicken, gelangt die Nachricht über den Secure WebSocket zum Broker und kommt über Ihr eigenes Abonnement sofort zurück. Öffnen Sie die Seite in zwei Tabs, sehen Sie, dass jeder Tab sein eigenes zufälliges Topic erhält und die Tabs sich gegenseitig nicht sehen. Um ein Topic zu teilen, tragen Sie in beiden fest dasselbe Topic connectmq/demo/<your-id>/chat ein.

Einige Hinweise zu den Optionen:

  • clientId muss nicht leer und eindeutig sein. Der öffentliche Bereich lehnt eine leere Client ID ab, und zwei Clients mit derselben ID werfen sich gegenseitig ständig hinaus.
  • protocolVersion: 5 verwendet MQTT 5. Nutzen Sie 4 für MQTT 3.1.1, falls nötig.
  • keepalive: 30 sorgt dafür, dass der Client bei Leerlauf ein PINGREQ sendet, damit Broker und etwaige Proxys wissen, dass er noch lebt.
  • reconnectPeriod: 2000 lässt MQTT.js zwei Sekunden nach einem Abbruch automatisch neu verbinden.

Sie können die Nachrichten des Browsers auch mit der Mosquitto-CLI in einem Terminal mitlesen, denn TCP- und WebSocket-Clients teilen sich dieselben Topics. Ersetzen Sie abc12345 durch die ID, die im Topic der Seite angezeigt wird:

mosquitto_sub -h broker.connectmq.com -p 1883 -i cli-watch-abc12345 -t "connectmq/demo/abc12345/#" -v

MQTT über WebSocket in Node.js

Node.js kann einfaches TCP nutzen, doch WebSocket ist praktisch, wenn Ihr Server hinter einem Proxy oder einer Firewall steht, die nur HTTPS-ähnlichen Verkehr erlaubt, oder wenn Sie Code mit einer Browser-App teilen möchten. Installieren Sie MQTT.js mit npm install mqtt und speichern Sie Folgendes als ws-client.mjs:

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();
});

Starten Sie es mit node ws-client.mjs. Die Ausgabe sieht etwa so aus:

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}

Der einzige Unterschied zu einem TCP-Client ist die URL. Tauschen Sie sie gegen mqtt://broker.connectmq.com:1883, und der restliche Code bleibt gleich. Wenn Sie die qos-Werte oben verstehen möchten, lesen Sie MQTT QoS-Stufen erklärt.

Fehlerbehebung bei MQTT-über-WebSocket-Verbindungen

Die meisten Probleme zeigen sich als Verbindung, die nie connect erreicht oder sich ständig neu verbindet. Öffnen Sie die Entwicklertools des Browsers, prüfen Sie die Konsole und den Netzwerk-Tab (Filter auf WS) und vergleichen Sie mit dieser Tabelle.

Symptom Wahrscheinliche Ursache Lösung
Fehler „Mixed Content“, Verbindung blockiert Eine https://-Seite versucht, ws:// zu öffnen wss://broker.connectmq.com:8084/mqtt verwenden
Handshake schlägt fehl, HTTP 404 im Netzwerk-Tab Fehlender oder falscher Pfad /mqtt an die URL anhängen
Handshake schlägt auf 8083 oder 8084 fehl Schema und Port vertauscht (ws auf 8084, wss auf 8083) ws gehört zu 8083, wss zu 8084
Sie vermuten ein CORS-Problem WebSocket unterliegt nicht wie fetch/XHR den CORS-Regeln Die echte Ursache suchen: URL, Port, TLS oder Zugangsdaten
Verbindet sich und trennt alle paar Sekunden Zwei Clients mit derselben Client ID Pro Tab oder Gerät eine eindeutige ID erzeugen
Verbindung direkt nach CONNECT abgelehnt Leere Client ID oder falscher Benutzername/falsches Passwort Nicht leere Client ID setzen; Zugangsdaten im Portal prüfen
Abbruch nach einer Phase der Inaktivität Keepalive zu lang für einen Proxy oder ein Mobilfunknetz keepalive: 30 oder weniger verwenden
Funktioniert lokal, scheitert im Firmennetz Proxy oder Firewall blockiert Nicht-Standard-Ports Aus einem anderen Netz testen oder die IT bitten, ausgehenden Verkehr auf Port 8084 freizugeben

Zwei davon verdienen einen genaueren Blick.

Mixed Content

Browser blockieren unsichere Unterressourcen auf sicheren Seiten. Wird Ihr Dashboard über https:// ausgeliefert, wird jede ws://-Verbindung abgelehnt, bevor sie den Browser verlässt – der Broker bekommt sie nie zu sehen. Die Lösung ist immer wss://. Der unverschlüsselte Endpunkt ws://broker.connectmq.com:8083/mqtt ist nur für Seiten sinnvoll, die von http://localhost oder als lokale Datei geöffnet werden.

Konflikte bei der Client ID

MQTT erlaubt pro Client ID nur eine Verbindung. Kommt eine zweite Verbindung mit derselben ID, schließt der Broker die erste. Im Browser passiert das oft, wenn ein Nutzer dieselbe Seite in zwei Tabs öffnet und die Client ID fest codiert ist. Bei aktiviertem automatischem Reconnect kämpfen beide Tabs dann endlos um die ID. Hängen Sie pro Tab ein zufälliges Suffix an. Auf einem privaten ConnectMQ-Broker sind Client IDs auf die ausgegebene Client ID und deren _suffix-Varianten beschränkt – verwenden Sie also YOUR_CLIENT_ID_tab1, YOUR_CLIENT_ID_tab2 usw.

Produktion: Zugangsdaten aus dem Portal verwenden

Der öffentliche Bereich ist zum Testen gedacht: Alles, was dort veröffentlicht wird, ist für jeden lesbar, und es gelten enge Limits (64 KB pro Nachricht, 10 Nachrichten pro Sekunde und Client). Für eine echte Anwendung legen Sie im Portal einen privaten Broker an und verbinden sich mit den generierten Zugangsdaten:

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,
});

Beachten Sie bei Browser-Apps folgende Punkte:

  • Verwenden Sie in der Produktion immer wss. Benutzername und Passwort werden im CONNECT-Paket übertragen, der Transport muss also verschlüsselt sein.
  • Betrachten Sie Zugangsdaten im Browser als sichtbar. Alles, was an einen Browser ausgeliefert wird, kann dessen Nutzer lesen. Geben Sie der Web-App eigene Zugangsdaten, statt Geräte-Zugangsdaten wiederzuverwenden, und betten Sie sie nicht in öffentliche Seiten ein.
  • Beachten Sie die Planlimits. Jeder offene Tab ist eine Verbindung. Der Plan Serverless (Free) erlaubt bis zu 25 gleichzeitige Verbindungen, was für Prototypen passt. Produktive Dashboards sind besser bei Serverless (Paid) mit bis zu 1.000 Verbindungen oder auf einem Dedicated-Cluster aufgehoben.
  • Behandeln Sie Reconnects sauber. Zeigen Sie einen Statusindikator an und abonnieren Sie erneut oder setzen Sie auf eine persistente Session, wenn die Verbindung zurückkehrt.

Weitere Tipps zur Absicherung finden Sie in MQTT-Sicherheit: Best Practices.

Starten Sie mit ConnectMQ

Sie können MQTT über WebSocket sofort mit dem öffentlichen Endpunkt wss://broker.connectmq.com:8084/mqtt testen. Wenn Sie bereit für ein echtes Dashboard sind, registrieren Sie sich kostenlos unter app.connectmq.com (kostenloser Serverless-Plan, ohne Kreditkarte), legen Sie einen Broker an und verbinden Sie sich mit Ihrem eigenen Benutzernamen, Passwort und Ihrer Client ID. Mit dem integrierten MQTT-Client im Browser und dem Live-Topic-Explorer des Portals prüfen Sie ganz einfach, ob Ihre Web-App das veröffentlicht, was Sie erwarten.

Häufig gestellte Fragen

Welchen Port verwendet MQTT über WebSocket?

Es gibt keinen einheitlichen Standardport. Bei broker.connectmq.com nutzt unverschlüsseltes WebSocket Port 8083 und Secure WebSocket Port 8084, jeweils mit dem Pfad /mqtt.

Ist MQTT über WebSocket langsamer als MQTT über TCP?

Der Overhead ist gering. Nach dem einmaligen HTTP-Upgrade wird jedes MQTT-Paket in einen WebSocket-Frame verpackt, der nur wenige Bytes hinzufügt. Für die meisten Anwendungen liegt die Latenz daher nahe an der von reinem TCP.

Brauche ich einen Backend-Server, um MQTT im Browser zu nutzen?

Nein. Mit MQTT über WebSocket verbindet sich der Browser direkt mit dem Broker. Ein Backend ist nur nötig, wenn Sie Zugangsdaten vom Client fernhalten oder eigene Geschäftslogik ergänzen möchten.

Gilt CORS für MQTT über WebSocket?

Nein. WebSocket-Verbindungen unterliegen nicht den CORS-Preflight-Prüfungen wie fetch- und XHR-Anfragen. Schlägt eine Verbindung fehl, prüfen Sie stattdessen URL, Port, Pfad und Zugangsdaten.

Können Browser-Clients und ESP32-Geräte dieselben Topics nutzen?

Ja. Der Broker leitet Nachrichten unabhängig vom Transport nach Topic weiter, sodass ein Browser über WSS und ein Gerät über TCP-Port 1883 auf dieselben Topics veröffentlichen und sie abonnieren können. Die Geräteseite behandelt die ESP32-MQTT-Anleitung.

Verwandte Artikel

Die besten MQTT-CLI-Tools zum Testen, Skripten und Debuggen

Ein praxisnaher Vergleich von mosquitto_pub/sub, MQTTX CLI, HiveMQ MQTT CLI, der MQTT.js-CLI, curl und mqttui – mit demselben Test gegen broker.connectmq.com, damit Sie das richtige Tool zum Skripten und Debuggen wählen.

8 Min. Lesezeit

Alle Artikel →

Ihr privater MQTT-Broker ist nur wenige Klicks entfernt

Konto anlegen, Broker-Zugangsdaten erhalten und das erste Gerät verbinden — ohne Server, die installiert, gepatcht oder skaliert werden müssen.