WebTransport verwenden

WebTransport ist eine API, die bidirektionale Client-Server-Messaging mit niedriger Latenz bietet. Hier erfahren Sie mehr über die Anwendungsfälle und darüber, wie Sie Feedback für die Zukunft der 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. Das Senden von Daten wird sowohl unzuverlässig über die Datagram APIs als auch zuverlässig über die Streams APIs unterstützt.

Datagramme sind ideal für das Senden und Empfangen von Daten geeignet, für die keine starken 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 auch nicht. Bei der Übertragung können sie in beliebiger Reihenfolge ankommen. Diese Eigenschaften machen die Datagram APIs ideal für die bestmögliche Datenübertragung mit niedriger Latenz. Sie können sich Datagramme als UDP-Nachrichten (User Datagram Protocol) vorstellen, die verschlüsselt und überlastungsgesteuert sind.

Die Stream-APIs bieten im Gegensatz dazu eine zuverlässige, geordnete Datenübertragung. Sie eignen sich gut für Szenarien, in denen Sie einen oder mehrere Streams geordneter Daten senden oder empfangen müssen. Die Verwendung mehrerer WebTransport-Streams entspricht dem Aufbau mehrerer TCP-Verbindungen. Da HTTP/3 jedoch im Hintergrund das weniger komplexe QUIC-Protokoll verwendet, können die Streams ohne so großen Aufwand geöffnet und geschlossen werden.

Anwendungsfälle

Dies ist eine kleine Liste der Möglichkeiten, wie Entwickler WebTransport nutzen können.

  • Senden des Spielstatus in regelmäßigen Abständen mit minimaler Latenz über kleine, unzuverlässige Nachrichten, die nicht in der richtigen Reihenfolge erfolgen, an einen Server
  • Empfangen von Medienstreams, die von einem Server mit minimaler Latenz übertragen werden, unabhängig von anderen Datenstreams.
  • Benachrichtigungen empfangen, die von einem Server gesendet werden, während eine Webseite geöffnet ist.

Wir würden gerne mehr darüber erfahren, wie Sie WebTransport nutzen möchten.

Unterstützte Browser

Unterstützte Browser

  • Chrome: 97. <ph type="x-smartling-placeholder">
  • Edge: 97. <ph type="x-smartling-placeholder">
  • Firefox: 114 <ph type="x-smartling-placeholder">
  • Safari: wird nicht unterstützt. <ph type="x-smartling-placeholder">

Quelle

Wie bei allen Funktionen, die keine universelle Browserunterstützung haben, ist die defensive Programmierung über die Funktionserkennung eine Best Practice.

Aktueller Status

Schritt Status
1. Erklärende 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

Beziehung von WebTransport zu anderen Technologien

Ist WebTransport ein Ersatz für WebSockets?

Vielleicht. In manchen Anwendungsfällen sind entweder WebSockets oder WebTransport gültige Kommunikationsprotokolle.

Die WebSockets-Kommunikation basiert auf einem einzelnen, zuverlässigen, geordneten Nachrichtenstrom, der für einige Arten von Kommunikationsanforderungen in Ordnung ist. Wenn Sie diese Eigenschaften benötigen, können Sie sie auch von den Stream-APIs von WebTransport bereitstellen. Im Gegensatz dazu bieten die Datagram APIs von WebTransport eine Lieferung mit niedriger Latenz, ohne Garantien hinsichtlich Zuverlässigkeit oder Reihenfolge. Daher sind sie kein direkter Ersatz für WebSockets.

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

WebTransport ist Teil eines neuen Spezifikationsentwurfs. Daher ist das WebSocket-Ökosystem rund um Client- und Serverbibliotheken derzeit viel robuster. Wenn Sie ein Gerät benötigen, das sofort einsatzbereit ist mit gängigen Serverkonfigurationen und einer umfassenden Webclient-Unterstützung ist WebSockets heute die bessere Wahl.

Ist WebTransport dasselbe wie eine UDP Socket API?

Nein. WebTransport ist keine UDP Socket API. Während WebTransport HTTP/3 verwendet, das im Hintergrund UDP verwendet, WebTransport stellt Anforderungen an die Verschlüsselung und Überlastungskontrolle, die es mehr als nur eine einfache UDP Socket API machen.

Ist WebTransport eine Alternative zu WebRTC-Datenkanälen?

Ja, für Client-Server-Verbindungen. WebTransport hat viele der gleichen Eigenschaften wie WebRTC-Datenkanäle, wobei sich die zugrunde liegenden Protokolle unterscheiden.

Im Allgemeinen erfordert der Betrieb eines HTTP/3-kompatiblen Servers weniger Einrichtung und Konfiguration als der Betrieb eines WebRTC-Servers, bei dem mehrere Protokolle (ICE, DTLS und SCTP) verstanden werden müssen, um eine funktionierende Übertragung zu ermöglichen. WebRTC umfasst viel mehr bewegliche Elemente, die zu fehlgeschlagenen Client/Server-Verhandlungen führen können.

Die WebTransport API wurde für die Anwendungsfälle von Webentwicklern entwickelt und sollte eher wie das Schreiben von Code für moderne Webplattformen als mit den Datenkanalschnittstellen von WebRTC aussehen. Im Gegensatz zu WebRTC wird WebTransport innerhalb von Web Workers unterstützt, sodass Sie Client-Server-Kommunikation unabhängig von einer bestimmten HTML-Seite durchführen können. Da WebTransport eine mit Streams kompatible Schnittstelle zur Verfügung stellt, werden Optimierungen bezüglich Rückstand unterstützt.

Wenn Sie jedoch bereits eine funktionierende WebRTC-Client/-Server-Einrichtung haben, mit der Sie zufrieden sind, bietet der Wechsel zu WebTransport möglicherweise nicht viele Vorteile.

Jetzt ausprobieren

Die beste Möglichkeit, mit WebTransport zu experimentieren, ist die Einrichtung eines kompatiblen HTTP/3-Servers. Sie können diese Seite dann mit einem grundlegenden JavaScript-Client verwenden, um die Client-Server-Kommunikation zu testen.

Außerdem gibt es unter webtransport.day einen von der Community betriebenen Echo-Server.

API verwenden

WebTransport basiert auf modernen Webplattform-Primitiven wie der Streams API. Sie stützt sich 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 sowohl unidirektionale als auch 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 sollte https sein. Sie müssen die Portnummer explizit angeben.

Du solltest das Promise ready verwenden, um zu warten, bis die Verbindung hergestellt wurde. Dieses Versprechen wird erst erfüllt, wenn die Einrichtung abgeschlossen ist, und wird abgelehnt, wenn die Verbindung in der QUIC/TLS-Phase fehlschlägt.

Das closed-Promise wird erfüllt, wenn die Verbindung normal beendet wird, und lehnt ab, wenn die Schließung unerwartet war.

Wenn der Server die Verbindung aufgrund eines Client-Anzeigefehlers ablehnt (z.B. weil der Pfad der URL ungültig ist), wird closed abgelehnt, während ready weiterhin ungelöst ist.

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

Wenn eine WebTransport-Instanz mit einem Server verbunden ist, können Sie damit diskrete Datenbits, sogenannte Datagrams, senden und empfangen.

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

Bei beiden 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 mithilfe von WebTransport auch Daten über die zugehörigen Streams APIs senden und empfangen.

Jeder Block aller Streams ist ein Uint8Array. Im Gegensatz zu den Datagram APIs sind diese Streams zuverlässig. Jeder Stream ist jedoch unabhängig, sodass die Reihenfolge der Daten in den einzelnen Streams nicht garantiert werden kann.

WebTransportSendStream

Ein WebTransportSendStream wird vom Webclient mit der Methode createUnidirectionalStream() einer WebTransport-Instanz erstellt, die ein Promise für das 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 tatsächlich 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}`);
}

Senden Sie entsprechend der Methode abort() der WritableStreamDefaultWriter eine RESET\_STREAM an den Server. Bei der Verwendung von abort() kann der Browser alle ausstehenden Daten verwerfen, 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 eines WebTransportReceiveStream ist ein zweistufiger Prozess für einen Webclient. Zuerst wird das Attribut incomingUnidirectionalStreams einer WebTransport-Instanz aufgerufen, die eine ReadableStream zurückgibt. Jeder Block dieser ReadableStream ist wiederum ein WebTransportReceiveStream, mit dem Uint8Array-Instanzen gelesen werden können, die vom Server gesendet wurden.

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 Sperrungen von Streams mithilfe des closed-Promise von ReadableStreamDefaultReader erkennen. Wenn die zugrunde liegende HTTP/3-Verbindung mit dem FIN-Bit geschlossen wird, wird das Promise closed erfüllt, nachdem alle Daten gelesen wurden. Wenn die HTTP/3-Verbindung abrupt geschlossen wird (z. B. durch RESET\_STREAM), wird das closed-Promise 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 ein Promise mithilfe der createBidirectionalStream()-Methode einer WebTransport-Instanz erstellen, die ein Promise für ein WebTransportBidirectionalStream zurückgibt.

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

Mit dem Attribut incomingBidirectionalStreams einer WebTransport-Instanz, die ein ReadableStream zurückgibt, können Sie auf ein vom Server erstelltes WebTransportBidirectionalStream-Objekt warten. Jeder Chunk dieser ReadableStream ist wiederum ein 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
}

Ein WebTransportBidirectionalStream ist eine Kombination aus WebTransportSendStream und WebTransportReceiveStream. In den Beispielen aus den beiden vorherigen Abschnitten wird ihre Verwendung erläutert.

Weitere Beispiele

Der WebTransport-Spezifikationsentwurf enthält eine Reihe zusätzlicher Inline-Beispiele sowie eine vollständige Dokumentation für alle Methoden und Eigenschaften.

WebTransport in den Chrome-Entwicklertools

WebTransport wird von den Chrome-Entwicklertools derzeit nicht unterstützt. Sie können „Markieren“ diesem Chrome-Problem, um über Updates der Entwicklertools-Oberfläche informiert zu werden.

Polyfill

Polyfill (oder ein Ponyfill, das Funktionen als eigenständiges Modul zur Verfügung stellt) namens webtransport-ponyfill-websocket zur Implementierung einiger WebTransport-Funktionen. Lesen Sie die Einschränkungen in README des Projekts, um festzustellen, ob diese Lösung für Ihren Anwendungsfall geeignet ist.

Überlegungen zu Datenschutz und Sicherheit

Eine verlässliche Anleitung finden Sie im entsprechenden Abschnitt des Spezifikationsentwurfs.

Feedback

Das Chrome-Team möchte wissen, wie Sie diese API halten und was Sie davon halten.

Feedback zum API-Design

Gibt es etwas an der API, das umständlich ist oder nicht wie erwartet funktioniert? Oder fehlen noch Teile, die du für die Umsetzung deiner Idee benötigst?

Sie können ein Problem im Web Transport GitHub-Repository melden oder Ihre Gedanken zu einem bestehenden Problem hinzufügen.

Probleme bei der Implementierung?

Haben Sie bei der Implementierung von Chrome einen Fehler gefunden?

Melden Sie den Fehler unter https://new.crbug.com. Gib so viele Details wie möglich und eine einfache Anleitung zum Reproduzieren an.

Möchten Sie die API verwenden?

Deine öffentliche Unterstützung hilft Chrome dabei, Funktionen zu priorisieren, und zeigt anderen Browseranbietern, wie wichtig es ist, diese zu unterstützen.

Allgemeine Disussionen

Für allgemeine Fragen oder Probleme, die in keine der anderen Kategorien passen, können Sie die Google-Gruppe „web-transport-dev“ nutzen.

Danksagungen

Dieser Artikel enthält Informationen aus der WebTransport Explainer, der Entwurfsspezifikation und den dazugehörigen Designdokumenten. Vielen Dank an die jeweiligen Autoren für die Bereitstellung dieser Grundlage.

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