WebTransport ist eine API, die bidirektionales Client-Server-Messaging mit niedriger Latenz bietet. Weitere Informationen zu den Anwendungsfällen und dazu, 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. Sie unterstützt das Senden von Daten sowohl unzuverlässig über die Datagramm-APIs als auch zuverlässig über die Streams-APIs.
Datagramme eignen sich ideal zum Senden und Empfangen von Daten, 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 werden möglicherweise nicht erfolgreich übertragen und können in beliebiger Reihenfolge eintreffen. Diese Eigenschaften machen die Datagramm-APIs ideal für die Datenübertragung mit niedriger Latenz und Best-Effort-Prinzip. Datagramme können als User Datagram Protocol (UDP)-Nachrichten betrachtet werden, die jedoch verschlüsselt sind und bei denen die Überlastung kontrolliert wird.
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 geordneten Daten senden oder empfangen müssen. Die Verwendung mehrerer WebTransport-Streams ist analog zum Herstellen mehrerer TCP-Verbindungen. Da HTTP/3 jedoch das schlankere QUIC-Protokoll verwendet, können sie ohne großen Aufwand geöffnet und geschlossen werden.
Anwendungsfälle
Hier finden Sie eine kleine Liste mit möglichen Anwendungsfällen für WebTransport.
- Der Spielstatus wird in regelmäßigen Abständen mit minimaler Latenz über kleine, unzuverlässige, ungeordnete Nachrichten an einen Server gesendet.
- Medienstreams, die von einem Server gepusht werden, mit minimaler Latenz empfangen, unabhängig von anderen Datenstreams.
- Benachrichtigungen von einem Server erhalten, während eine Webseite geöffnet ist.
Wir würden uns freuen, mehr darüber zu erfahren, wie Sie WebTransport verwenden möchten.
Unterstützte Browser
Wie bei allen Funktionen, die nicht von allen Browsern unterstützt werden, ist es empfehlenswert, Funktionserkennung zu verwenden.
Aktueller Status
Schritt | Status |
---|---|
1. Erklärung 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 infrage kommen.
Die WebSocket-Kommunikation basiert auf einem einzelnen, zuverlässigen, geordneten Stream von Nachrichten, was für einige Arten von Kommunikationsanforderungen in Ordnung ist. Wenn Sie diese Eigenschaften benötigen, können Sie sie auch über die Streams APIs von WebTransport erhalten. Im Vergleich dazu bieten die Datagramm-APIs von WebTransport eine Übertragung mit geringer Latenz, ohne dass Zuverlässigkeit oder Reihenfolge garantiert werden. Sie sind also kein direkter Ersatz für WebSockets.
Wenn Sie WebTransport über die Datagramm-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 bietet QUIC 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 Spezifikationsversion. Daher ist das WebSocket-Ökosystem rund um Client- und Serverbibliotheken derzeit viel robuster. Wenn Sie etwas benötigen, das mit gängigen Servereinstellungen und mit breiter Webclient-Unterstützung „out of the box“ funktioniert, sind WebSockets heute die bessere Wahl.
Ist WebTransport dasselbe wie eine UDP-Socket-API?
Nein. WebTransport ist keine UDP Socket API. WebTransport verwendet HTTP/3, das wiederum UDP verwendet. WebTransport hat jedoch Anforderungen an die Verschlüsselung und die Ü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 der gleichen Eigenschaften wie WebRTC-Datenkanäle, obwohl die zugrunde liegenden Protokolle unterschiedlich sind.
Im Allgemeinen erfordert der Betrieb eines HTTP/3-kompatiblen Servers weniger Einrichtung und Konfiguration als die Wartung eines WebRTC-Servers, bei dem mehrere Protokolle (ICE, DTLS und SCTP) erforderlich sind, um einen funktionierenden Transport zu erhalten. WebRTC umfasst viele weitere Komponenten, die zu fehlgeschlagenen Client-/Server-Verhandlungen führen können.
Die WebTransport API wurde für die Anwendungsfälle von Webentwicklern entwickelt und sollte sich eher wie das Schreiben von modernem Webplattformcode als die Verwendung der Datenkanalschnittstellen von WebRTC anfühlen. Im Gegensatz zu WebRTC wird WebTransport in Webworkern unterstützt. So können Sie Client-Server-Kommunikation unabhängig von einer bestimmten HTML-Seite durchführen. Da WebTransport eine Streams-kompatible Schnittstelle bereitstellt, werden Optimierungen in Bezug auf Gegendruck unterstützt.
Wenn Sie jedoch bereits eine funktionierende WebRTC-Client-/Serverkonfiguration haben, mit der Sie zufrieden sind, bietet ein Wechsel zu WebTransport möglicherweise nicht viele Vorteile.
Jetzt ausprobieren
Am besten probieren Sie WebTransport aus, indem Sie einen kompatiblen HTTP/3-Server starten. Anschließend können Sie diese Seite mit einem einfachen JavaScript-Client verwenden, um die Client-/Server-Kommunikation zu testen.
Außerdem ist unter webtransport.day ein von der Community verwalteter Echoserver verfügbar.
API verwenden
WebTransport wurde auf Grundlage moderner Webplattform-Primitiven wie der Streams API entwickelt. Es basiert stark auf Promises 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 sollte https
sein. Sie müssen die Portnummer explizit angeben.
Verwenden Sie das ready
-Promise, um zu warten, bis die Verbindung hergestellt wurde. Dieses Promise 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 geschlossen wird, und abgelehnt, wenn der Schließvorgang unerwartet war.
Wenn der Server die Verbindung aufgrund eines Clienthinweis-Fehlers ablehnt (z.B. der Pfad der URL ist ungültig), wird closed
abgelehnt, während ready
nicht aufgelöst wird.
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.t>hen(() = {
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, sogenannte Datagramme, senden und empfangen.
Der writeable
-Getter gibt ein WritableStream
zurück, das ein Webclient verwenden kann, um Daten an den Server zu senden. Der readable
-Getter gibt ein ReadableStream
zurück, sodass 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.
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 auch WebTransport verwenden, um Daten über die Streams-APIs zu senden und zu empfangen.
Jeder Chunk aller Streams ist ein Uint8Array
. Im Gegensatz zu den Datagram-APIs sind diese Streams zuverlässig. Da jeder Stream jedoch unabhängig ist, kann die Reihenfolge der Daten in den Streams nicht garantiert werden.
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()
des WritableStreamDefaultWriter
, um den zugehörigen HTTP/3-Stream zu schließen. Der Browser versucht, alle ausstehenden Daten zu senden, bevor der zugehörige Stream 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: ${erro
r}`);
}
Verwenden Sie entsprechend die Methode abort()
des WritableStreamDefaultWriter
, um ein RESET_STREAM
an den Server zu senden. Wenn Sie abort()
verwenden, werden möglicherweise alle ausstehenden Daten, die noch nicht gesendet wurden, vom Browser verworfen.
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
Eine WebTransportReceiveStream
wird vom Server initiiert. Das Abrufen eines WebTransportReceiveStream
für einen Webclient erfolgt in zwei Schritten. Zuerst wird das Attribut incomingUnidirectionalStreams
einer WebTransport
-Instanz aufgerufen, das ein ReadableStream
zurückgibt. Jeder Chunk dieses ReadableStream
ist wiederum ein WebTransportReceiveStream
, mit dem 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);
}
Sie können das Schließen des Streams mit dem closed
-Promise von ReadableStreamDefaultReader
erkennen. Wenn der zugrunde liegende HTTP/3-Stream mit dem FIN-Bit geschlossen wird, wird das closed
-Promise erfüllt, nachdem alle Daten gelesen wurden. Wenn der HTTP/3-Stream 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.');
}).ca>tch(() = {
console.error('The receiveStream closed abrup
tly.');
});
WebTransportBidirectionalStream
Ein WebTransportBidirectionalStream
kann entweder vom Server oder vom Client erstellt werden.
Web-Clients können einen mit der Methode createBidirectionalStream()
einer WebTransport
-Instanz erstellen, die ein Promise 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
Sie können mit dem Attribut incomingBidirectionalStreams
einer WebTransport
-Instanz, das ein ReadableStream
zurückgibt, auf ein vom Server erstelltes WebTransportBidirectionalStream
warten. Jeder Chunk dieses 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
}
Eine WebTransportBidirectionalStream
ist lediglich eine Kombination aus einem WebTransportSendStream
und einem WebTransportReceiveStream
. In den Beispielen aus den beiden vorherigen Abschnitten wird die Verwendung der einzelnen Methoden erläutert.
Weitere Beispiele
Die WebTransport-Spezifikation (Draft) enthält eine Reihe zusätzlicher Inline-Beispiele sowie eine vollständige Dokumentation für alle Methoden und Eigenschaften.
WebTransport in den Chrome-Entwicklertools
Leider unterstützen die Chrome-Entwicklertools WebTransport derzeit nicht. Sie können dieses Chrome-Problem mit einem Sternchen markieren, um über Updates der Entwicklertools-Oberfläche benachrichtigt zu werden.
Polyfill
Es ist ein Polyfill (oder besser gesagt ein Ponyfill, das Funktionalität als eigenständiges Modul bietet) namens webtransport-ponyfill-websocket
verfügbar, das einige der Funktionen von WebTransport implementiert. Lesen Sie sich die Einschränkungen in der README
des Projekts genau durch, um festzustellen, ob diese Lösung für Ihren Anwendungsfall geeignet ist.
Überlegungen zu Datenschutz und Sicherheit
Im entsprechenden Abschnitt der Entwurfsspezifikation finden Sie maßgebliche Informationen.
Feedback
Das Chrome-Team möchte gern wissen, was Sie über diese API denken und welche Erfahrungen Sie damit gemacht haben.
Feedback zum API-Design
Gibt es etwas an der API, das umständlich ist oder nicht wie erwartet funktioniert? Oder fehlen Ihnen noch Informationen, um Ihre Idee umzusetzen?
Melden Sie ein Problem im WebTransport-GitHub-Repository oder fügen Sie einem bestehenden Problem Ihre Gedanken hinzu.
Probleme bei der Implementierung?
Haben Sie einen Fehler in der Chrome-Implementierung gefunden?
Melden Sie einen Fehler unter https://new.crbug.com. Geben Sie so viele Details wie möglich an und fügen Sie eine einfache Anleitung zur Reproduktion hinzu.
Sie planen, die API zu verwenden?
Ihre öffentliche Unterstützung hilft Chrome, Funktionen zu priorisieren, und zeigt anderen Browseranbietern, wie wichtig es ist, sie zu unterstützen.
- Senden Sie einen Tweet an @ChromiumDev mit dem Hashtag
#WebTransport
und geben Sie an, wo und wie Sie die Funktion verwenden.
Allgemeine Disussionen
Für allgemeine Fragen oder Probleme, die nicht in eine der anderen Kategorien passen, können Sie die Google-Gruppe „web-transport-dev“ verwenden.
Danksagungen
Dieser Artikel enthält Informationen aus dem WebTransport Explainer, der Spezifikationsentwurf und zugehörigen Designdokumenten. Vielen Dank an die jeweiligen Autoren für diese Grundlage.
Das Hero-Bild in diesem Beitrag stammt von Robin Pierre auf Unsplash.