Broker-Tests

MQTT über WebSockets testen (ws und wss)

MQTT-WebSocket-Endpunkt Schritt für Schritt testen: Pfad /mqtt, Subprotokoll mqtt, Handshake-Checks mit curl und wscat, Browser-DevTools und ein MQTT.js-Test.

Aktualisiert · 8 Min. Lesezeit

MQTT über WebSockets testen (ws und wss)

Um MQTT über WebSockets zu testen, prüfst du die Verbindung in zwei Stufen: zuerst das HTTP-Upgrade (richtige URL, richtiger Pfad, Subprotokoll mqtt, 101 Switching Protocols), dann eine echte MQTT-Sitzung im Socket (CONNECT, CONNACK, Publish, Subscribe). Die meisten WebSocket-Probleme — 404, geschlossene Sockets, Mixed-Content-Blockaden — passieren in der ersten Stufe, bevor MQTT überhaupt ins Spiel kommt.

Die Beispiele nutzen broker.connectmq.com: ws:// auf Port 8083 und wss:// auf Port 8084, jeweils mit dem Pfad /mqtt.

So sieht eine funktionierende MQTT-WebSocket-Verbindung aus

Eine MQTT-WebSocket-URL besteht aus vier Teilen, und jeder davon kann falsch sein:

TeilBeispielTypischer Fehler
Schemawss://ws:// aus einer HTTPS-Seite (als Mixed Content blockiert)
Hostbroker.connectmq.comIP-Adresse mit wss — Zertifikat passt nicht
Port8084TCP-Port 1883 oder TLS-Port 8883 verwendet
Pfad/mqttFehlender oder falscher Pfad — 404 Not Found

Der Client sendet außerdem den Header Sec-WebSocket-Protocol: mqtt. Der Broker muss mit HTTP/1.1 101 Switching Protocols antworten und Sec-WebSocket-Protocol: mqtt zurückgeben. Danach transportiert der Socket ganz normale binäre MQTT-Pakete — dasselbe CONNECT und CONNACK wie über TCP. Hintergründe findest du unter MQTT über WebSockets.

Stufe 1: den Handshake testen

Mit curl

curl kann den Upgrade-Request von Hand senden und die rohe Antwort anzeigen. So trennst du den HTTP-Teil von jeder MQTT-Bibliothek:

WebSocket-Handshake prüfen
curl -i --http1.1 --max-time 5 \
  -H "Connection: Upgrade" \
  -H "Upgrade: websocket" \
  -H "Sec-WebSocket-Version: 13" \
  -H "Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==" \
  -H "Sec-WebSocket-Protocol: mqtt" \
  https://broker.connectmq.com:8084/mqtt

Mit http://...:8083/mqtt testest du den unverschlüsselten Listener. Ein gesunder Endpunkt antwortet:

Erwartete Antwort
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: mqtt

Anschließend wartet curl bis --max-time, weil der Socket offen bleibt — das ist so gewollt. Andere Antworten zeigen dir, was zu reparieren ist:

AntwortBedeutung
101 ohne Sec-WebSocket-Protocol: mqttBroker oder Proxy verwirft das Subprotokoll; Browser schließen den Socket
404 Not FoundFalscher Pfad — probiere /mqtt, / oder den dokumentierten Pfad deines Brokers (Details)
400 Bad Request / 426 Upgrade RequiredUpgrade-Header fehlen — oft ein Proxy, der sie nicht weiterreicht
502 Bad GatewayDer Reverse Proxy erreicht den WebSocket-Listener des Brokers nicht
Empty reply from server oder ResetDer Port spricht normales MQTT/TLS, kein WebSocket
SSL-ZertifikatsfehlerDieselben TLS-Probleme wie auf 8883 — das Zertifikat muss zum Hostnamen passen

Steht der Broker hinter Nginx oder einem anderen Proxy, bedeuten ein 400 oder ein fehlendes Subprotokoll fast immer, dass die Header Upgrade und Connection nicht durchgereicht werden — siehe MQTT hinter einem Nginx-Proxy.

Mit wscat

wscat ist ein kleiner WebSocket-Client, der das Subprotokoll korrekt aushandelt:

wscat
npx wscat -c wss://broker.connectmq.com:8084/mqtt -s mqtt

Connected (press CTRL+C to quit) bedeutet: Handshake und Subprotokoll sind in Ordnung. Nach ein paar Sekunden schließt der Broker den Socket, weil kein MQTT-CONNECT-Paket kam — das ist normal und bestätigt sogar, dass dort ein MQTT-Broker lauscht. Ohne -s mqtt lehnen viele Broker das Upgrade ab, was sich gut als Negativtest eignet.

Stufe 2: eine echte MQTT-Sitzung testen

Die mosquitto-Kommandozeilen-Clients können sich nicht über WebSockets verbinden, also brauchst du einen WebSocket-fähigen Client. Am schnellsten geht es mit dem Online-MQTT-Client: wss://-URL eingeben, verbinden, ein Test-Topic abonnieren und darauf publishen. Klappt das, ist die Broker-Seite korrekt und jedes verbleibende Problem liegt in deiner Anwendung.

Für einen automatisierten Check läuft dieses MQTT.js-5-Skript in Node.js oder fast unverändert im Browser:

ws-check.mjs (MQTT.js 5)
import mqtt from "mqtt";

const url = "wss://broker.connectmq.com:8084/mqtt";
const topic = `testmqtt/ws/${Math.random().toString(16).slice(2, 10)}`;

const client = mqtt.connect(url, {
  protocolVersion: 5,
  username: process.env.MQTT_USER,
  password: process.env.MQTT_PASS,
  connectTimeout: 5000,
  reconnectPeriod: 0, // beim Testen schnell fehlschlagen
});

const started = Date.now();
client.on("connect", (connack) => {
  console.log(`CONNACK reason ${connack.reasonCode ?? 0} after ${Date.now() - started} ms`);
  client.subscribe(topic, { qos: 1 }, () => client.publish(topic, "ping over websocket", { qos: 1 }));
});
client.on("message", (t, payload) => {
  console.log(`round trip ok on ${t}: ${payload}`);
  client.end();
});
client.on("error", (err) => { console.error("error:", err.message); process.exit(1); });
client.on("close", () => console.log("socket closed"));

MQTT.js setzt das Subprotokoll mqtt automatisch. Python geht genauso — paho-mqtt 2.x mit transport="websockets":

ws_check.py (paho-mqtt 2.x)
import os
import paho.mqtt.client as mqtt

c = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, transport="websockets", protocol=mqtt.MQTTv5)
c.ws_set_options(path="/mqtt")
c.tls_set()  # für ws:// auf Port 8083 entfernen
c.username_pw_set(os.environ["MQTT_USER"], os.environ["MQTT_PASS"])
c.on_connect = lambda cl, u, f, rc, p: print("CONNACK:", rc)
c.connect("broker.connectmq.com", 8084)
c.loop_forever()

Der Standard-WebSocket-Pfad von paho ist bereits /mqtt, ws_set_options ist hier also optional — Broker mit / oder einem eigenen Pfad antworten aber mit 404, bis du ihn explizit setzt.

Debugging mit den Browser-DevTools

Wenn sich eine Web-App nicht verbinden kann, zeigt dir der Browser jedes Detail des Handshakes:

  1. Öffne die DevTools → Network, filtere nach WS (Chrome) bzw. wähle WS im Typfilter (Firefox) und lade die Seite neu.
  2. Klick auf den Socket-Request. Prüfe unter Headers den Status (101), URL und Pfad sowie, ob Request und Response Sec-WebSocket-Protocol: mqtt enthalten.
  3. Öffne den Tab Messages (Chrome) bzw. Response (Firefox). Der erste ausgehende Frame ist das binäre MQTT-CONNECT, der erste eingehende das CONNACK. Geht das CONNECT raus und der Socket schließt ohne CONNACK, hat der Broker die MQTT-Sitzung abgelehnt (Zugangsdaten, Client-ID) — nicht den WebSocket.
  4. Such in der Console nach Fehlern wie diesen:
Typische Konsolenfehler
WebSocket connection to 'wss://broker.example.com:8084/mqtt' failed:
Mixed Content: The page at 'https://app.example.com/' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://broker.example.com:8083/mqtt'. This request has been blocked; this endpoint must be available over WSS.

Der erste, ohne Text nach dem Doppelpunkt, ist der generische Browserfehler — meist falscher Port, Pfad oder ein Zertifikatsproblem; schau in den Network-Tab. Der zweite lässt sich nur durch den Wechsel auf wss:// beheben (Mixed Content). Ein Close-Code 1006 bedeutet, dass die Verbindung ohne ordentlichen Close-Frame abgebrochen ist — oft ein Proxy-Timeout oder ein Broker, der die Verbindung ablehnt. Die vollständige Liste der Ursachen findest du unter MQTT WebSocket connection failed.

WebSocket-Test-Checkliste

  1. curl auf die wss://-URL liefert 101 und gibt Sec-WebSocket-Protocol: mqtt zurück.
  2. wscat mit -s mqtt verbindet sich; ohne lehnt der Broker ab oder schließt.
  3. Ein echter Client erhält ein CONNACK und schafft einen Publish/Subscribe-Roundtrip.
  4. Der Browser verbindet sich von einer HTTPS-Seite mit wss://, ohne Konsolenfehler.
  5. Über deinen Proxy oder Load Balancer überleben inaktive Verbindungen länger als das Keep-Alive-Intervall.
  6. Zugangsdaten und ACLs verhalten sich auf dem WebSocket-Listener genauso wie auf TCP.

WebSocket-Endpunkt im Browser testen

WebSocket-Probleme wirken nur so lange mysteriös, bis du sie in zwei Teile zerlegst. Beweise das HTTP-Upgrade mit curl oder wscat, dann die MQTT-Sitzung mit einem echten Client — und du weißt in Minuten, ob URL, Proxy oder MQTT-Zugangsdaten zu korrigieren sind.

Häufig gestellte Fragen

Welchen WebSocket-Pfad nutzt MQTT?

Es gibt keinen einheitlichen Standard. /mqtt ist am verbreitetsten (EMQX, HiveMQ und ConnectMQ nutzen ihn, Proxys vor Mosquitto leiten ihn meist weiter), manche Broker lauschen aber auf / oder einem eigenen Pfad. Ein falscher Pfad liefert beim Handshake meist HTTP 404.

Welches WebSocket-Subprotokoll verwendet MQTT?

mqtt, sowohl für MQTT 3.1.1 als auch für MQTT 5. Alte MQTT-3.1-Clients nutzten mqttv3.1. Der Client sendet es in Sec-WebSocket-Protocol, und der Broker muss es in der 101-Antwort zurückgeben — sonst trennen Browser die Verbindung.

Kann sich mosquitto_pub über WebSockets verbinden?

Nein. Die mosquitto-Kommandozeilen-Clients sprechen MQTT nur über TCP und TLS. Zum Testen eines WebSocket-Listeners nimmst du einen Browser-Client, MQTT.js, paho-mqtt mit transport="websockets" oder einen Desktop-Client wie MQTTX.