Signatur
Beschreibung
Das Interface WebTransportDatagramDuplexStream gehört zur WebTransport API. Man erzeugt es nicht selbst, sondern bekommt es über die Eigenschaft WebTransport.datagrams einer bestehenden Verbindung. Es kombiniert einen ReadableStream (readable) für eingehende und einen WritableStream (writable) für ausgehende Datagramme. Beide transportieren Uint8Array-Blöcke.
Datagramme laufen über HTTP/3 bzw. QUIC und sind unzuverlässig: Pakete können verloren gehen, in anderer Reihenfolge ankommen und werden nicht erneut gesendet. Dafür fällt das Head-of-Line-Blocking weg und die Latenz ist minimal. Gut geeignet sind Echtzeit-Daten, bei denen nur der neueste Stand zählt, zum Beispiel Spielerpositionen in Online-Spielen, Telemetrie, Sensorwerte oder Audio- und Video-Frames mit geringer Latenz.
Über zusätzliche Eigenschaften lässt sich das Puffern steuern:
maxDatagramSize: größte Nutzlast pro Datagramm in Byte (nur lesbar)incomingHighWaterMark/outgoingHighWaterMark: Puffergröße in Anzahl DatagrammenincomingMaxAge/outgoingMaxAge: Höchstalter in Millisekunden, danach werden gepufferte Datagramme verworfen (null= kein Limit)
Brauchen Sie zuverlässige, geordnete Übertragung, nehmen Sie stattdessen createBidirectionalStream() oder createUnidirectionalStream().
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $readable | ReadableStream<Uint8Array> | Nur lesbar. Stream der vom Server empfangenen Datagramme. | |
| $writable | WritableStream<Uint8Array> | Nur lesbar. Stream zum Senden von Datagrammen an den Server. In neueren Implementierungen kann es auch über createWritable() erzeugt werden. |
|
| $maxDatagramSize | number | Nur lesbar. Größte erlaubte Nutzlast pro Datagramm in Byte. Hängt von der Path-MTU ab, meist etwas über 1000 Byte. | |
| $incomingHighWaterMark | number | implementierungsabhängig | Größe des Eingangspuffers in Datagrammen, bevor eingehende Pakete verworfen werden. |
| $outgoingHighWaterMark | number | implementierungsabhängig | Größe des Ausgangspuffers in Datagrammen; bestimmt den Gegendruck (Backpressure) beim Schreiben. |
| $incomingMaxAge | number | null | null | Höchstalter eingehender Datagramme im Puffer in Millisekunden. |
| $outgoingMaxAge | number | null | null | Höchstalter ausgehender Datagramme in Millisekunden. Ältere Pakete werden nicht mehr gesendet. |
Rückgabewert
transport.datagrams. Es gibt keinen öffentlichen Konstruktor.Beispiele
Verbindung aufbauen und Datagramm senden
const transport = new WebTransport('https://example.com:4433/game');
await transport.ready;
// Duplex-Stream für Datagramme holen
const { datagrams } = transport;
console.log('Max. Größe:', datagrams.maxDatagramSize);
const writer = datagrams.writable.getWriter();
const payload = new TextEncoder().encode('ping');
await writer.write(payload);
writer.releaseLock();
Eingehende Datagramme fortlaufend lesen
const transport = new WebTransport('https://example.com:4433/telemetry');
await transport.ready;
const reader = transport.datagrams.readable.getReader();
const decoder = new TextDecoder();
try {
while (true) {
const { value, done } = await reader.read();
if (done) break;
console.log('Empfangen:', decoder.decode(value));
}
} catch (err) {
console.error('Datagramm-Stream abgebrochen:', err);
}
Spielerposition mit Altersgrenze und Größenprüfung senden
const transport = new WebTransport('https://example.com:4433/game');
await transport.ready;
const dg = transport.datagrams;
// Veraltete Positionen nach 50 ms verwerfen
dg.outgoingMaxAge = 50;
dg.outgoingHighWaterMark = 10;
const writer = dg.writable.getWriter();
const sendPosition = async (x, y) => {
const buf = new Float32Array([x, y]);
const bytes = new Uint8Array(buf.buffer);
if (bytes.byteLength > dg.maxDatagramSize) {
throw new RangeError('Datagramm zu groß');
}
await writer.ready; // Backpressure beachten
writer.write(bytes);
};
setInterval(() => sendPosition(Math.random() * 100, Math.random() * 100), 16);
// Wichtig · Fallstricke
- Keine Zustellgarantie: Datagramme können verloren gehen, doppelt oder in anderer Reihenfolge ankommen. Wenn nötig, Sequenznummern selbst mitschicken und auf Anwendungsebene auswerten.
- Größenlimit: Pakete über
maxDatagramSizewerden verworfen und nicht fragmentiert. Große Daten müssen Sie selbst aufteilen oder über Streams senden. - Nur ein Lock:
getReader()bzw.getWriter()sperren den Stream. Rufen SiereleaseLock()auf, bevor anderer Code darauf zugreift. - Kompatibilität: Unterstützt ab Chromium 97 und Firefox 114. Safari unterstützt WebTransport noch nicht. Die API ist nur in sicheren Kontexten (HTTPS) verfügbar, der Server muss HTTP/3 mit WebTransport können. Prüfen Sie die Unterstützung mit
'WebTransport' in globalThis. - Die Eigenschaften
incomingMaxAge,outgoingMaxAgeund die HighWaterMarks sind je nach Browser unterschiedlich weit umgesetzt. Werte werden eventuell ignoriert. - Wird die Verbindung geschlossen (
transport.close()oder Netzwerkfehler), brechenreadableundwritablemit einem Fehler ab. Lese-Schleifen deshalb intry/catchpacken.