WebTransport verwenden

WebTransport ist eine API, die bidirektionales Messaging mit niedriger Latenz zwischen Client und Server bietet. Hier erfahren Sie mehr über die Anwendungsfälle und wie Sie Feedback zur zukünftigen Implementierung geben können.

Hintergrund

Was ist WebTransport?

WebTransport ist eine Web-API, die das HTTP/3-Protokoll als bidirektionalen Transport verwendet. Es ist für die bidirektionale Kommunikation zwischen einem Webclient und einem HTTP/3-Server vorgesehen. Es unterstützt das Senden von Daten sowohl unzuverlässig über seine Datagram APIs als auch zuverlässig über seine Streams APIs.

Datagramme eignen sich ideal für das Senden und Empfangen von Daten, für die keine strengen Zustellgarantien erforderlich sind. Die Größe einzelner Datenpakete ist durch die maximale Übertragungseinheit (MTU) der zugrunde liegenden Verbindung begrenzt. Sie können erfolgreich übertragen werden oder nicht. Wenn sie übertragen werden, können sie in einer beliebigen Reihenfolge eintreffen. Diese Eigenschaften machen die Datagram-APIs ideal für die Best-Effort-Datenübertragung mit niedriger Latenz. Sie können Datagramme als UDP-Nachrichten (User Datagram Protocol) betrachten, die jedoch verschlüsselt und schadlos sind.

Die Streams APIs bieten dagegen eine zuverlässige, geordnete Datenübertragung. Sie eignen sich gut für Szenarien, in denen Sie einen oder mehrere Streams mit sortierten Daten senden oder empfangen müssen. Die Verwendung mehrerer WebTransport-Streams ist mit dem Herstellen mehrerer TCP-Verbindungen vergleichbar. Da HTTP/3 jedoch das leichtere QUIC-Protokoll verwendet, können sie ohne großen Overhead geöffnet und geschlossen werden.

Anwendungsfälle

Hier sind einige Möglichkeiten, wie Entwickler WebTransport verwenden können.

  • Der Spielstatus wird in regelmäßigen Intervallen mit minimaler Latenz über kleine, unzuverlässige, nicht in der richtigen Reihenfolge gesendete Nachrichten an einen Server gesendet.
  • Empfang von Medienstreams, die von einem Server mit minimaler Latenz gepusht werden, unabhängig von anderen Datenstreams.
  • Empfang von Benachrichtigungen, die von einem Server gesendet werden, während eine Webseite geöffnet ist.

Wir würden uns gern darüber austauschen, wie Sie WebTransport verwenden möchten.

Unterstützte Browser

Unterstützte Browser

  • Chrome: 97.
  • Edge: 97.
  • Firefox: 114.
  • Safari: Nicht unterstützt.

Quelle

Wie bei allen Funktionen, die nicht von allen Browsern unterstützt werden, ist es eine bewährte Methode, proaktiv über die Funktionserkennung zu programmieren.

Aktueller Status

Schritt Status
1. Erläuternde Mitteilung erstellen Abschließen
2. Ersten Entwurf der Spezifikation erstellen Abschließen
3. Feedback einholen und Design iterieren Abgeschlossen
4. Ursprungstest Abgeschlossen
5. Launch Chromium 97

WebTransport im Vergleich zu anderen Technologien

Ist WebTransport ein Ersatz für WebSockets?

Vielleicht. Es gibt Anwendungsfälle, in denen entweder WebSockets oder WebTransport als Kommunikationsprotokolle verwendet werden können.

WebSocket-Kommunikation basiert auf einem einzelnen, zuverlässigen, sortierten Nachrichtenstream, was für einige Arten von Kommunikationsanforderungen in Ordnung ist. Wenn Sie diese Eigenschaften benötigen, können sie auch von den Streams APIs von WebTransport bereitgestellt werden. Im Vergleich dazu bieten die Datagram APIs von WebTransport eine Übermittlung mit geringer Latenz, ohne Garantien für Zuverlässigkeit oder Reihenfolge. Sie sind also kein direkter Ersatz für WebSockets.

Wenn Sie WebTransport über die Datagram APIs oder über mehrere gleichzeitige Streams API-Instanzen verwenden, müssen Sie sich keine Gedanken über Head-of-Line-Blocking machen, was bei WebSockets ein Problem sein kann. Außerdem ergeben sich Leistungsvorteile beim Herstellen neuer Verbindungen, da der zugrunde liegende QUIC-Handshake schneller ist als das Starten von TCP über TLS.

WebTransport ist Teil einer neuen Spezifikationsvorlage. Daher ist das WebSocket-System mit Client- und Serverbibliotheken derzeit viel robuster. Wenn Sie eine Lösung benötigen, die ohne zusätzliche Konfigurationen mit gängigen Serverkonfigurationen funktioniert und einen umfassenden Webclient-Support bietet, sind WebSockets derzeit die bessere Wahl.

Ist WebTransport dasselbe wie eine UDP-Socket-API?

Nein. WebTransport ist keine UDP Socket API. WebTransport verwendet zwar HTTP/3, das wiederum UDP verwendet, aber WebTransport hat Anforderungen an Verschlüsselung und Überlastungssteuerung, die es zu mehr als einer einfachen UDP-Socket-API machen.

Ist WebTransport eine Alternative zu WebRTC-Datenkanälen?

Ja, für Client-Server-Verbindungen. WebTransport hat viele Eigenschaften gemeinsam mit WebRTC-Datenkanälen, obwohl die zugrunde liegenden Protokolle unterschiedlich sind.

Im Allgemeinen ist für die Ausführung eines HTTP/3-kompatiblen Servers weniger Einrichtung und Konfiguration erforderlich als für die Verwaltung eines WebRTC-Servers. Für einen funktionierenden Transport müssen mehrere Protokolle (ICE, DTLS und SCTP) verstanden werden. WebRTC umfasst viele weitere Variablen, die zu fehlgeschlagenen Client-/Server-Verhandlungen führen können.

Die WebTransport API wurde speziell für Webentwickler entwickelt und sollte eher an das Schreiben von modernen Webplattformcode erinnern als an die Verwendung der Datenkanalschnittstellen von WebRTC. Im Gegensatz zu WebRTC wird WebTransport in Webworkern unterstützt. So können Sie die Client-Server-Kommunikation unabhängig von einer bestimmten HTML-Seite ausführen. Da WebTransport eine Streams-kompatible Schnittstelle bereitstellt, unterstützt es Optimierungen im Zusammenhang mit Backpressure.

Wenn Sie jedoch bereits eine funktionierende WebRTC-Client/Server-Konfiguration haben, mit der Sie zufrieden sind, bietet die Umstellung auf WebTransport möglicherweise nicht viele Vorteile.

Jetzt ausprobieren

Am besten starten Sie einen kompatiblen HTTP/3-Server, um mit WebTransport zu experimentieren. Sie können diese Seite dann mit einem einfachen JavaScript-Client verwenden, um die Client/Server-Kommunikation zu testen.

Außerdem ist ein von der Community gepflegter Echo-Server unter webtransport.day verfügbar.

API verwenden

WebTransport wurde auf der Grundlage moderner Webplattform-Primitive wie der Streams API entwickelt. Er basiert stark auf Versprechen und funktioniert gut mit async und await.

Die aktuelle WebTransport-Implementierung in Chromium unterstützt drei verschiedene Arten von Traffic: Datagramme sowie unidirektionale und bidirektionale Streams.

Verbindung zu einem Server herstellen

Sie können eine Verbindung zu einem HTTP/3-Server herstellen, indem Sie eine WebTransport-Instanz erstellen. Das Schema der URL muss https sein. Sie müssen die Portnummer explizit angeben.

Sie sollten das ready-Promise verwenden, um zu warten, bis die Verbindung hergestellt ist. Diese Zusicherung wird erst erfüllt, wenn die Einrichtung abgeschlossen ist. Andernfalls wird sie abgelehnt, wenn die Verbindung in der QUIC-/TLS-Phase fehlschlägt.

Das closed-Versprechen wird erfüllt, wenn die Verbindung normal geschlossen wird, und abgelehnt, wenn die Schließung unerwartet war.

Wenn der Server die Verbindung aufgrund eines Fehlers bei der Clientanfrage ablehnt (z.B. wenn der Pfad der URL ungültig ist), wird closed abgelehnt, während ready weiterhin ungelöst bleibt.

const url = 'https://example.com:4999/foo/bar';
const transport = new WebTransport(url);

// Optionally, set up functions to respond to
// the connection closing:
transport.closed.then(() => {
  console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
}).catch((error) => {
  console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
});

// Once .ready fulfills, the connection can be used.
await transport.ready;

Datagram APIs

Sobald Sie eine WebTransport-Instanz haben, die mit einem Server verbunden ist, können Sie damit einzelne Datenbits senden und empfangen, die als datagrams bezeichnet werden.

Der writeable-Getter gibt eine WritableStream zurück, mit der ein Webclient Daten an den Server senden kann. Der readable-Getter gibt ein ReadableStream zurück, mit dem Sie auf Daten vom Server warten können. Beide Streams sind von Natur aus unzuverlässig. Es ist also möglich, dass die von Ihnen geschriebenen Daten nicht vom Server empfangen werden und umgekehrt.

Für beide Arten von Streams werden Uint8Array-Instanzen für die Datenübertragung verwendet.

// Send two datagrams to the server.
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);

// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
  const {value, done} = await reader.read();
  if (done) {
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

Streams APIs

Nachdem Sie eine Verbindung zum Server hergestellt haben, können Sie auch WebTransport verwenden, um Daten über die Streams APIs zu senden und zu empfangen.

Jeder Teil aller Streams ist ein Uint8Array. Im Gegensatz zu den Datagram APIs sind diese Streams zuverlässig. Da jeder Stream jedoch unabhängig ist, ist die Datenreihenfolge zwischen den Streams nicht garantiert.

WebTransportSendStream

Ein WebTransportSendStream wird vom Webclient mithilfe der createUnidirectionalStream()-Methode einer WebTransport-Instanz erstellt, die ein Versprechen für die WebTransportSendStream zurückgibt.

Verwenden Sie die Methode close() von WritableStreamDefaultWriter, um die zugehörige HTTP/3-Verbindung zu schließen. Der Browser versucht, alle ausstehenden Daten zu senden, bevor die zugehörige Verbindung geschlossen wird.

// Send two Uint8Arrays to the server.
const stream = await transport.createUnidirectionalStream();
const writer = stream.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
try {
  await writer.close();
  console.log('All data has been sent.');
} catch (error) {
  console.error(`An error occurred: ${error}`);
}

Verwenden Sie die Methode abort() der WritableStreamDefaultWriter, um eine RESET\_STREAM an den Server zu senden. Wenn Sie abort() verwenden, verwirft der Browser möglicherweise alle ausstehenden Daten, die noch nicht gesendet wurden.

const ws = await transport.createUnidirectionalStream();
const writer = ws.getWriter();
writer.write(...);
writer.write(...);
await writer.abort();
// Not all the data may have been written.

WebTransportReceiveStream

Ein WebTransportReceiveStream wird vom Server initiiert. Das Abrufen einer WebTransportReceiveStream erfolgt für einen Webclient in zwei Schritten. Zuerst wird das incomingUnidirectionalStreams-Attribut einer WebTransport-Instanz aufgerufen, das ein ReadableStream zurückgibt. Jeder Teil dieser ReadableStream ist wiederum eine WebTransportReceiveStream, mit der vom Server gesendete Uint8Array-Instanzen gelesen werden können.

async function readFrom(receiveStream) {
  const reader = receiveStream.readable.getReader();
  while (true) {
    const {done, value} = await reader.read();
    if (done) {
      break;
    }
    // value is a Uint8Array
    console.log(value);
  }
}

const rs = transport.incomingUnidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is an instance of WebTransportReceiveStream
  await readFrom(value);
}

Du kannst die Schließung des Streams mit dem closed-Versprechen von ReadableStreamDefaultReader erkennen. Wenn die zugrunde liegende HTTP/3-Verbindung mit dem FIN-Bit geschlossen wird, wird das closed-Versprechen erfüllt, nachdem alle Daten gelesen wurden. Wenn die HTTP/3-Verbindung abrupt geschlossen wird (z. B. durch RESET\_STREAM), wird das closed-Versprechen abgelehnt.

// Assume an active receiveStream
const reader = receiveStream.readable.getReader();
reader.closed.then(() => {
  console.log('The receiveStream closed gracefully.');
}).catch(() => {
  console.error('The receiveStream closed abruptly.');
});

WebTransportBidirectionalStream

Ein WebTransportBidirectionalStream kann entweder vom Server oder vom Client erstellt werden.

Webclients können eine mit der createBidirectionalStream()-Methode einer WebTransport-Instanz erstellen, die ein Versprechen für eine WebTransportBidirectionalStream zurückgibt.

const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream

Du kannst mit dem incomingBidirectionalStreams-Attribut einer WebTransport-Instanz auf ein vom Server erstelltes WebTransportBidirectionalStream warten, das ein ReadableStream zurückgibt. Jeder Teil dieser ReadableStream ist wiederum eine WebTransportBidirectionalStream.

const rs = transport.incomingBidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is a WebTransportBidirectionalStream
  // value.readable is a ReadableStream
  // value.writable is a WritableStream
}

Eine WebTransportBidirectionalStream ist nur eine Kombination aus WebTransportSendStream und WebTransportReceiveStream. In den Beispielen aus den beiden vorherigen Abschnitten wird die Verwendung der einzelnen Funktionen erläutert.

Weitere Beispiele

Die WebTransport-Entwurfsspezifikation enthält eine Reihe zusätzlicher Inline-Beispiele sowie eine vollständige Dokumentation für alle Methoden und Properties.

WebTransport in den Chrome-Entwicklertools

Leider wird WebTransport derzeit nicht von den Chrome-Entwicklertools unterstützt. Sie können dieses Chrome-Problem mit einem Stern markieren, um über Updates in der Benutzeroberfläche der Entwicklertools benachrichtigt zu werden.

Polyfill

Es gibt eine Polyfill (oder Ponyfill, die Funktionen als eigenständiges Modul bereitstellt) namens webtransport-ponyfill-websocket, die einige der Funktionen von WebTransport implementiert. Lesen Sie sich die Einschränkungen in der README des Projekts sorgfältig durch, um festzustellen, ob diese Lösung für Ihren Anwendungsfall geeignet ist.

Datenschutz- und Sicherheitsaspekte

Weitere Informationen finden Sie im entsprechenden Abschnitt der Entwurfsspezifikation.

Feedback

Das Chrome-Team würde gern wissen, was Sie von dieser API halten und wie Sie sie verwenden.

Feedback zum API-Design

Gibt es etwas an der API, das unpraktisch ist oder nicht wie erwartet funktioniert? Oder fehlen Ihnen noch Teile, die Sie für die Umsetzung Ihrer Idee benötigen?

Melden Sie ein Problem im GitHub-Repository für Web Transport oder fügen Sie Ihre Gedanken zu einem vorhandenen Problem hinzu.

Problem bei der Implementierung?

Haben Sie einen Fehler in der Chrome-Implementierung gefunden?

Melden Sie den Fehler unter https://new.crbug.com. Geben Sie dabei so viele Details wie möglich an und fügen Sie eine einfache Anleitung zum Nachstellen des Fehlers hinzu.

Sie möchten die API verwenden?

Ihre öffentliche Unterstützung hilft uns, die Priorität von Funktionen in Chrome festzulegen, und zeigt anderen Browseranbietern, wie wichtig es ist, sie zu unterstützen.

  • Tweeten Sie an @ChromiumDev und verwenden Sie dabei den Hashtag #WebTransport sowie Details dazu, wo und wie Sie die Funktion verwenden.

Allgemeine Disussionen

Die Google-Gruppe „web-transport-dev“ können Sie für allgemeine Fragen oder Probleme verwenden, die in keine der anderen Kategorien fallen.

Danksagungen

Dieser Artikel enthält Informationen aus der Erläuterung zu WebTransport, der Entwurfsspezifikation und den zugehörigen Designdokumenten. Vielen Dank an die jeweiligen Autoren für diese Grundlage.

Das Hero-Image in diesem Beitrag stammt von Robin Pierre auf Unsplash.