WebTransport est une API offrant une messagerie client-serveur bidirectionnelle à faible latence. Découvrez ses cas d'utilisation et comment envoyer des commentaires sur l'avenir de l'implémentation.
Contexte
Qu'est-ce que WebTransport ?
WebTransport est une API Web qui utilise le protocole HTTP/3 comme transport bidirectionnel. Il est destiné aux communications bidirectionnelles entre un client Web et un serveur HTTP/3. Il permet l'envoi de données de manière non fiable via ses API de datagramme et via ses API de flux de manière fiable.
Les datagrammes sont parfaits pour envoyer et recevoir des données qui n'ont pas besoin de garanties de livraison solides. Les paquets de données individuels sont limités en taille par l'unité de transmission maximale (MTU) de la connexion sous-jacente, et peuvent être transmis ou non avec succès. S'ils sont transférés, ils peuvent arriver dans un ordre arbitraire. Ces caractéristiques font des API de datagrammes idéales pour une transmission de données optimale et à faible latence. Vous pouvez considérer les datagrammes comme des messages du protocole de datagramme utilisateur (UDP), mais chiffrés et maîtrisés en congestion.
Les API de flux, quant à elles, permettent un transfert de données fiable et ordonné. Elles sont bien adaptées aux scénarios dans lesquels vous devez envoyer ou recevoir un ou plusieurs flux de données ordonnées. L'utilisation de plusieurs flux WebTransport est comparable à l'établissement de plusieurs connexions TCP. Cependant, comme HTTP/3 utilise en arrière-plan le protocole plus léger QUIC, il est possible d'ouvrir et de fermer ces flux sans trop d'efforts.
Cas d'utilisation
Il s'agit d'une courte liste des façons dont les développeurs peuvent utiliser WebTransport.
- Envoyer l'état du jeu à intervalle régulier avec une latence minimale à un serveur via de petits messages non fiables et dans le désordre
- Recevoir des flux multimédias envoyés depuis un serveur avec une latence minimale, indépendamment des autres flux de données
- Réception de notifications envoyées par un serveur lorsqu'une page Web est ouverte.
Nous aimerions en savoir plus sur la façon dont vous prévoyez d'utiliser WebTransport.
Prise en charge des navigateurs
Navigateurs pris en charge
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
- <ph type="x-smartling-placeholder">
Comme pour toutes les fonctionnalités qui ne sont pas compatibles avec les navigateurs, nous vous conseillons de coder de manière défensive grâce à la détection de fonctionnalités.
État actuel
Étape | État |
---|---|
1. Créer une vidéo explicative | Fin |
2. Créer l'ébauche initiale de la spécification | Fin |
3. Recueillir les commentaires et itérer la conception | Terminé |
4. Phase d'évaluation | Terminé |
5. Lancement | Chromium 97 |
Relation entre WebTransport et d'autres technologies
WebTransport remplace-t-il WebSockets ?
Peut-être. Dans certains cas, les protocoles de communication WebSockets ou WebTransport peuvent être des protocoles de communication valides.
Les communications WebSockets sont modélisées autour d'un flux de messages unique, fiable et ordonné, ce qui convient à certains types de besoins de communication. Si vous avez besoin de ces caractéristiques, les API de flux de WebTransport peuvent également les fournir. En comparaison, les API de datagramme de WebTransport offrent une diffusion à faible latence, sans garantie de fiabilité ni de classement. Elles ne remplacent donc pas directement WebSockets.
En utilisant WebTransport, via les API de datagramme ou via plusieurs instances simultanées de l'API Streams, vous n'avez pas à vous soucier du blocage en tête de ligne, qui peut être un problème avec WebSockets. En outre, l'établissement de nouvelles connexions offre des avantages en termes de performances, car le handshake QUIC sous-jacent est plus rapide que le démarrage de TCP sur TLS.
WebTransport fait partie d'un nouveau projet de spécification. À ce titre, l'écosystème WebSocket autour des bibliothèques clientes et de serveurs est actuellement beaucoup plus robuste. Si vous avez besoin d'une solution qui fonctionne immédiatement avec des configurations de serveur courantes et une compatibilité étendue avec les clients Web, WebSockets est aujourd'hui un meilleur choix.
WebTransport est-il identique à une API Socket UDP ?
Non. WebTransport n'est pas une API de socket UDP. Alors que WebTransport utilise HTTP/3, qui à son tour utilise UDP « en arrière-plan », WebTransport a des exigences de chiffrement et de contrôle de la congestion qui en font plus qu'une API Socket UDP de base.
WebTransport est-il une alternative aux canaux de données WebRTC ?
Oui, pour les connexions client-serveur. WebTransport partage de nombreuses propriétés des canaux de données WebRTC, bien que les protocoles sous-jacents soient différents.
En général, l'exécution d'un serveur compatible avec HTTP/3 nécessite moins de configuration que la maintenance d'un serveur WebRTC, ce qui implique de comprendre plusieurs protocoles (ICE, DTLS et SCTP) pour obtenir un transport fonctionnel. WebRTC implique beaucoup d'autres éléments mobiles qui pourraient entraîner l'échec des négociations client/serveur.
L'API WebTransport a été conçue pour répondre aux besoins des développeurs Web. Elle devrait ressembler davantage à l'écriture de code de plate-forme Web moderne qu'à l'utilisation des interfaces de canaux de données WebRTC. Contrairement à WebRTC, WebTransport est compatible avec les nœuds de calcul Web, qui vous permettent d'effectuer des communications client-serveur indépendamment d'une page HTML donnée. Étant donné que WebTransport expose une interface conforme à Streams, il accepte les optimisations liées à la contre-pression.
Toutefois, si vous disposez déjà d'une configuration client/serveur WebRTC opérationnelle et que vous êtes satisfait, le passage à WebTransport risque de ne pas offrir beaucoup d'avantages.
Essayer
La meilleure façon de tester WebTransport est de démarrer un serveur HTTP/3 compatible. Vous pouvez ensuite utiliser cette page avec un client JavaScript de base pour tester les communications client/serveur.
De plus, un serveur d'écho géré par la communauté est disponible à l'adresse webtransport.day.
Utilisation de l'API
WebTransport a été conçu sur la base des primitives des plates-formes Web modernes, telles que l'API Streams. Elle s'appuie fortement sur des promesses, et fonctionne bien avec async
et await
.
La mise en œuvre actuelle de WebTransport dans Chromium accepte trois types de trafic distincts: les datagrammes, ainsi que les flux unidirectionnels et bidirectionnels.
Connexion à un serveur
Vous pouvez vous connecter à un serveur HTTP/3 en créant une instance WebTransport
. Le schéma de l'URL doit être https
. Vous devez spécifier explicitement le numéro de port.
Vous devez utiliser la promesse ready
pour attendre que la connexion soit établie. Cette promesse ne sera honorée qu'une fois la configuration terminée et sera refusée si la connexion échoue à l'étape QUIC/TLS.
La promesse closed
est exécutée lorsque la connexion se ferme normalement et est refusée si la fermeture est inattendue.
Si le serveur refuse la connexion en raison d'une erreur client (par exemple, le chemin de l'URL n'est pas valide), cela entraîne le refus de closed
, tandis que ready
n'est pas résolu.
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;
API de datagramme
Une fois que vous disposez d'une instance WebTransport connectée à un serveur, vous pouvez l'utiliser pour envoyer et recevoir des bits de données distincts, appelés datagrammes.
Le getter writeable
renvoie un WritableStream
, qu'un client Web peut utiliser pour envoyer des données au serveur. Le getter readable
renvoie un ReadableStream
, ce qui vous permet d'écouter les données du serveur. Les deux flux sont intrinsèquement peu fiables. Il est donc possible que les données que vous écrivez ne soient pas reçues par le serveur, et inversement.
Les deux types de flux utilisent des instances Uint8Array
pour le transfert de données.
// 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);
}
API Streams
Une fois connecté au serveur, vous pouvez également utiliser WebTransport pour envoyer et recevoir des données via ses API Streams.
Chaque fragment de tous les flux est une Uint8Array
. Contrairement aux API Datagram, ces flux sont fiables. Cependant, chaque flux est indépendant. L'ordre des données entre les flux n'est donc pas garanti.
WebTransportSendStream
Un WebTransportSendStream
est créé par le client Web à l'aide de la méthode createUnidirectionalStream()
d'une instance WebTransport
, qui renvoie une promesse pour WebTransportSendStream
.
Utilisez la méthode close()
de WritableStreamDefaultWriter
pour fermer la connexion HTTP/3 associée. Le navigateur tente d'envoyer toutes les données en attente avant de fermer la connexion associée.
// 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}`);
}
De même, utilisez la méthode abort()
du WritableStreamDefaultWriter
pour envoyer un RESET\_STREAM
au serveur. Lorsque vous utilisez abort()
, le navigateur peut supprimer toutes les données en attente qui n'ont pas encore été envoyées.
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
Un WebTransportReceiveStream
est lancé par le serveur. L'obtention d'un WebTransportReceiveStream
est un processus en deux étapes pour un client Web. Tout d'abord, elle appelle l'attribut incomingUnidirectionalStreams
d'une instance WebTransport
, qui renvoie un ReadableStream
. Chaque fragment de ce ReadableStream
est, à son tour, un WebTransportReceiveStream
qui peut être utilisé pour lire les instances Uint8Array
envoyées par le serveur.
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);
}
Vous pouvez détecter la fermeture d'une diffusion à l'aide de la promesse closed
du ReadableStreamDefaultReader
. Lorsque la connexion HTTP/3 sous-jacente est fermée avec le bit FIN, la promesse closed
est remplie une fois toutes les données lues. Lorsque la connexion HTTP/3 est fermée brusquement (par exemple, par RESET\_STREAM
), la promesse closed
est refusée.
// 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
Un WebTransportBidirectionalStream
peut être créé par le serveur ou le client.
Les clients Web peuvent en créer une à l'aide de la méthode createBidirectionalStream()
d'une instance WebTransport
, qui renvoie une promesse pour un WebTransportBidirectionalStream
.
const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream
Vous pouvez écouter un WebTransportBidirectionalStream
créé par le serveur avec l'attribut incomingBidirectionalStreams
d'une instance WebTransport
, qui renvoie un ReadableStream
. Chaque fragment de ce ReadableStream
est, à son tour, un 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
}
Un WebTransportBidirectionalStream
est simplement la combinaison d'un WebTransportSendStream
et d'un WebTransportReceiveStream
. Les exemples des deux sections précédentes expliquent comment utiliser chacun d'eux.
Autres exemples
La spécification WebTransport inclut plusieurs exemples intégrés supplémentaires, ainsi qu'une documentation complète sur toutes les méthodes et propriétés.
WebTransport dans les outils de développement de Chrome
Malheureusement, les outils de développement de Chrome ne sont actuellement pas compatibles avec WebTransport. Vous pouvez activer le suivi ce problème lié à Chrome pour être informé des mises à jour disponibles dans l'interface des outils de développement.
Polyfill
Un polyfill (ou plutôt ponyfill qui fournit une fonctionnalité en tant que module autonome que vous pouvez utiliser) appelé
webtransport-ponyfill-websocket
qui implémente certaines des fonctionnalités
de WebTransport est disponible. Lisez attentivement les contraintes
README
du projet pour déterminer si cette solution peut fonctionner pour votre cas d'utilisation.
Points à prendre en compte concernant la confidentialité et la sécurité
Consultez la section correspondante du brouillon de spécification pour obtenir des conseils fiables.
Commentaires
L'équipe Chrome aimerait connaître votre avis et votre expérience avec cette API.
Commentaires sur la conception de l'API
Y a-t-il un aspect de l'API gênant ou qui ne fonctionne pas comme prévu ? Ou manque-t-il des éléments dont vous avez besoin pour mettre en œuvre votre idée ?
Signalez un problème dans le dépôt GitHub Transport Web ou ajoutez vos commentaires à un problème existant.
Vous rencontrez un problème lors de l'implémentation ?
Avez-vous détecté un bug dans l'implémentation de Chrome ?
Signalez un bug sur https://new.crbug.com. Fournissez autant de détails que possible, ainsi que des instructions simples pour reproduire le problème.
Vous prévoyez d'utiliser l'API ?
Votre assistance publique permet à Chrome de donner la priorité aux fonctionnalités et montre aux autres fournisseurs de navigateurs à quel point il est essentiel d'assurer leur assistance.
- Envoyez un tweet à @ChromiumDev en utilisant le hashtag.
#WebTransport
et des détails sur où et comment vous l'utilisez.
Discussion générale
Vous pouvez utiliser le groupe Google "web-transport-dev" pour les questions d'ordre général ou les problèmes qui n'entrent dans aucune des autres catégories.
Remerciements
Cet article intègre des informations issues du document WebTransport Explainer, du brouillon de spécification et des documents de conception associés. Merci aux auteurs respectifs d'avoir fourni ces bases.
L'image héros de ce post a été conçue par Robin Pierre sur Unsplash.