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
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.