Signatur
Beschreibung
Das Interface WebTransportBidirectionalStream gehört zur WebTransport API und steht für einen einzelnen bidirektionalen Stream innerhalb einer HTTP/3-WebTransport-Sitzung. Ein solcher Stream hat zwei Hälften: readable (ein WebTransportReceiveStream, also ein ReadableStream für eingehende Bytes) und writable (ein WebTransportSendStream, also ein WritableStream für ausgehende Bytes).
Die Übertragung ist zuverlässig und geordnet: Anders als bei Datagrammen (WebTransport.datagrams) kommen alle Bytes eines Streams vollständig und in der richtigen Reihenfolge an. Da jeder Stream unabhängig ist, blockiert ein verlorenes Paket in einem Stream die anderen nicht (kein Head-of-Line-Blocking wie bei WebSockets über TCP).
Man erhält Instanzen nicht über einen Konstruktor, sondern auf zwei Wegen:
- Selbst geöffnet über
await transport.createBidirectionalStream(). - Vom Gegenüber (Server) geöffnet, empfangen über den
ReadableStreamtransport.incomingBidirectionalStreams.
Typische Einsatzfälle sind Anfrage/Antwort-Protokolle (RPC), Spiele-Steuerbefehle oder Chat-Kanäle, bei denen jede logische Unterhaltung einen eigenen Stream bekommt. Das Interface ist in Fenstern und Web Workern verfügbar.
Parameter
| Name | Typ | Default | Beschreibung |
|---|---|---|---|
| $readable Pflicht | WebTransportReceiveStream (ReadableStream<Uint8Array>) | Schreibgeschützte Eigenschaft: Lesbares Ende des Streams für vom Gegenüber gesendete Bytes. Mit getReader() oder for await lesen. |
|
| $writable Pflicht | WebTransportSendStream (WritableStream<Uint8Array>) | Schreibgeschützte Eigenschaft: Beschreibbares Ende des Streams. Über getWriter() Daten als Uint8Array/ArrayBuffer senden; close() signalisiert das Ende (FIN). |
Rückgabewert
WebTransport.prototype.createBidirectionalStream() (als Promise) bzw. als Chunk von WebTransport.incomingBidirectionalStreams geliefert.Beispiele
Stream öffnen, Anfrage senden und Antwort lesen
const transport = new WebTransport('https://example.com:4433/rpc');
await transport.ready;
// Bidirektionalen Stream erzeugen
const stream = await transport.createBidirectionalStream();
// Anfrage schreiben
const writer = stream.writable.getWriter();
await writer.write(new TextEncoder().encode('PING'));
await writer.close(); // Senderichtung beenden (FIN)
// Antwort vollständig lesen
const decoder = new TextDecoder();
let antwort = '';
for await (const chunk of stream.readable) {
antwort += decoder.decode(chunk, { stream: true });
}
antwort += decoder.decode();
console.log('Antwort:', antwort);
Vom Server geöffnete Streams empfangen (Echo)
const transport = new WebTransport('https://example.com:4433/echo');
await transport.ready;
const handleStream = async ({ readable, writable }) => {
// Alles Empfangene direkt zurücksenden
await readable.pipeTo(writable);
console.log('Stream beendet');
};
const reader = transport.incomingBidirectionalStreams.getReader();
while (true) {
const { value: stream, done } = await reader.read();
if (done) break;
handleStream(stream).catch(err => console.error('Stream-Fehler:', err));
}
Stream mit Fehlercode abbrechen und Fehler auswerten
const transport = new WebTransport('https://example.com:4433/game');
await transport.ready;
const stream = await transport.createBidirectionalStream();
const writer = stream.writable.getWriter();
try {
await writer.write(new Uint8Array([1, 2, 3]));
// Senderichtung mit anwendungsspezifischem Code abbrechen (RESET_STREAM)
await writer.abort(new WebTransportError({ message: 'Abbruch', streamErrorCode: 42 }));
// Leserichtung ebenfalls verwerfen (STOP_SENDING)
await stream.readable.cancel();
console.log('Stream abgebrochen');
} catch (err) {
if (err instanceof WebTransportError) {
console.error(err.source, err.streamErrorCode);
}
}
// Wichtig · Fallstricke
- Kompatibilität: Chromium-Browser ab Version 97 und Firefox ab 114 unterstützen WebTransport; Safari hat (Stand 2024) noch keine Unterstützung. Vorher mit
'WebTransport' in globalThisprüfen und ggf. auf WebSockets zurückfallen. - Nur in sicheren Kontexten (HTTPS) verfügbar; der Server muss HTTP/3 mit WebTransport sprechen. Für Entwicklungszertifikate kann
serverCertificateHashesimWebTransport-Konstruktor genutzt werden (nur kurzlebige ECDSA-Zertifikate). - Es gibt keinen öffentlichen Konstruktor –
new WebTransportBidirectionalStream()wirft einenTypeError. - Ein Stream ist ein Byte-Strom, keine Nachrichtenfolge:
write()-Aufrufe können beim Empfänger zu anderen Chunk-Grenzen zusammengefasst oder aufgeteilt werden. Für Nachrichten eigene Längenpräfixe oder Trennzeichen verwenden. - Jede Richtung wird unabhängig beendet:
writable.close()schließt nur die Senderichtung; das Lesen bleibt möglich. Nicht geschlossene Writer/Reader halten Locks – vorpipeTo()keinen eigenen Reader/Writer anlegen. - Wird die Sitzung mit
transport.close()beendet oder bricht die Verbindung ab, werden beide Hälften mit einemWebTransportErrorfehlerhaft abgeschlossen – Fehler immer abfangen.