WebTransport est une API qui propose une messagerie client-serveur bidirectionnelle à faible latence. Découvrez ses cas d'utilisation et comment donner votre avis sur l'avenir de l'implémentation.
Arrière-plan
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 d'envoyer des données de manière non fiable via ses API de datagrammes et de manière fiable via ses API de flux.
Les datagrammes sont idéaux pour envoyer et recevoir des données qui ne nécessitent pas de fortes garanties de remise. La taille des paquets de données individuels est limitée par l'unité de transmission maximale (MTU) de la connexion sous-jacente. Ils peuvent être transmis ou non, et s'ils le sont, ils peuvent arriver dans n'importe quel ordre. Ces caractéristiques font des API de datagrammes un choix idéal pour la transmission de données à faible latence et avec le meilleur effort possible. Vous pouvez considérer les datagrammes comme des messages UDP (User Datagram Protocol), mais chiffrés et avec contrôle de congestion.
En revanche, les API de flux fournissent un transfert de données fiable et ordonné. Ils sont bien adaptés 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 analogue à l'établissement de plusieurs connexions TCP, mais comme HTTP/3 utilise le protocole QUIC plus léger en arrière-plan, ils peuvent être ouverts et fermés sans autant de surcharge.
Cas d'utilisation
Voici une petite liste des utilisations possibles de WebTransport par les développeurs.
- Envoi de l'état du jeu à intervalles réguliers avec une latence minimale à un serveur via de petits messages non fiables et dans le désordre.
- Recevoir des flux multimédias envoyés par un serveur avec une latence minimale, indépendamment des autres flux de données.
- Recevoir des 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
Comme pour toutes les fonctionnalités qui ne sont pas compatibles avec tous les navigateurs, il est recommandé de coder de manière défensive à l'aide de la détection de fonctionnalités.
État actuel
Étape | État |
---|---|
1. Créer un message d'explication | Fin |
2. Créer une première ébauche de spécification | Fin |
3. Recueillir des commentaires et itérer la conception | Terminé |
4. Essai Origin Trial | Terminé |
5. Lancement | Chromium 97 |
Relation de WebTransport avec d'autres technologies
WebTransport remplace-t-il WebSockets ?
Peut-être. Dans certains cas d'utilisation, WebSockets ou WebTransport peuvent être des protocoles de communication valides.
Les communications WebSockets sont modélisées autour d'un flux unique, fiable et ordonné de messages, 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 datagrammes de WebTransport offrent une distribution à faible latence, sans garantie de fiabilité ni d'ordre. Elles ne remplacent donc pas directement les WebSockets.
L'utilisation de WebTransport, via les API de datagrammes ou via plusieurs instances d'API Streams simultanées, signifie que vous n'avez pas à vous soucier du blocage en tête de file, qui peut être un problème avec WebSockets. De plus, l'établissement de nouvelles connexions présente 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'une nouvelle spécification provisoire. L'écosystème WebSocket autour des bibliothèques client et serveur est donc actuellement beaucoup plus robuste. Si vous avez besoin d'une solution qui fonctionne "prête à l'emploi" avec les configurations de serveur courantes et une large compatibilité avec les clients Web, WebSockets est un meilleur choix aujourd'hui.
WebTransport est-il identique à une API de socket UDP ?
Non. WebTransport n'est pas une API UDP Socket. Bien que WebTransport utilise HTTP/3, qui à son tour utilise UDP "en coulisses", WebTransport a des exigences en matière de chiffrement et de contrôle de la congestion qui en font plus qu'une simple API de socket UDP.
WebTransport est-il une alternative aux canaux de données WebRTC ?
Oui, pour les connexions client-serveur. WebTransport partage de nombreuses propriétés avec les 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 HTTP/3 nécessite moins de configuration que la maintenance d'un serveur WebRTC, qui implique de comprendre plusieurs protocoles (ICE, DTLS et SCTP) pour obtenir un transport fonctionnel. WebRTC implique beaucoup plus d'éléments mobiles qui peuvent entraîner l'échec des négociations client/serveur.
L'API WebTransport a été conçue en tenant compte des cas d'utilisation des développeurs Web. Elle devrait ressembler davantage à l'écriture de code de plate-forme Web moderne qu'à l'utilisation des interfaces de canal de données de WebRTC. Contrairement à WebRTC, WebTransport est compatible avec les Web Workers, ce qui vous permet d'effectuer des communications client-serveur indépendamment d'une page HTML donnée. Comme WebTransport expose une interface conforme à Streams, il est compatible avec les optimisations autour de la rétropression.
Toutefois, si vous disposez déjà d'une configuration client/serveur WebRTC fonctionnelle qui vous convient, le passage à WebTransport n'offrira peut-être pas beaucoup d'avantages.
Essayer
Le meilleur moyen d'expérimenter 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 sur webtransport.day.
Utiliser l'API
WebTransport a été conçu sur la base de primitives de plate-forme Web modernes, comme l'API Streams. Il s'appuie fortement sur les promesses et fonctionne bien avec async
et await
.
L'implémentation actuelle de WebTransport dans Chromium est compatible avec trois types de trafic distincts : les datagrammes, ainsi que les flux unidirectionnels et bidirectionnels.
Se connecter à 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 pas tenue tant que la configuration ne sera pas terminée et sera rejetée si la connexion échoue lors de l'étape QUIC/TLS.
La promesse closed
est tenue lorsque la connexion se ferme normalement et rejetée si la fermeture est inattendue.
Si le serveur refuse la connexion en raison d'une erreur d'indication du client (par exemple, le chemin d'accès de l'URL n'est pas valide), closed
est refusé, tandis que ready
reste non 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.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;
API Datagram
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.
L'accesseur writeable
renvoie un WritableStream
, qu'un client Web peut utiliser pour envoyer des données au serveur. L'accesseur readable
renvoie un ReadableStream
, ce qui vous permet d'écouter les données du serveur. Les deux flux étant intrinsèquement peu fiables, il est possible que les données que vous écrivez ne soient pas reçues par le serveur, et vice versa.
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 bloc de tous les flux est un Uint8Array
. Contrairement aux API Datagram, ces flux sont fiables. Toutefois, chaque flux est indépendant. L'ordre des données n'est donc pas garanti d'un flux à l'autre.
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 le WebTransportSendStream
.
Utilisez la méthode close()
de WritableStreamDefaultWriter
pour fermer le flux HTTP/3 associé. Le navigateur tente d'envoyer toutes les données en attente avant de fermer le flux associé.
// 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}`);
}
De même, utilisez la méthode abort()
de 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 initié par le serveur. L'obtention d'un WebTransportReceiveStream
est un processus en deux étapes pour un client Web. Tout d'abord, il appelle l'attribut incomingUnidirectionalStreams
d'une instance WebTransport
, qui renvoie un ReadableStream
. Chaque bloc 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 du flux à l'aide de la promesse closed
de ReadableStreamDefaultReader
. Lorsque le flux HTTP/3 sous-jacent est fermé avec le bit FIN, la promesse closed
est tenue une fois que toutes les données ont été lues. Lorsque le flux HTTP/3 est fermé de manière abrupte (par exemple, par RESET_STREAM
), la promesse closed
est rejetée.
// 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
Un WebTransportBidirectionalStream
peut être créé par le serveur ou le client.
Les clients Web peuvent en créer un à 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 bloc 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
n'est qu'une 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 provisoire de WebTransport inclut un certain nombre d'exemples intégrés supplémentaires, ainsi que la documentation complète de toutes les méthodes et propriétés.
WebTransport dans les outils pour les développeurs Chrome
Malheureusement, les Outils pour les développeurs Chrome ne sont actuellement pas compatibles avec WebTransport. Vous pouvez "suivre" ce problème Chrome pour recevoir des notifications sur les mises à jour de l'interface des outils de développement.
Rembourrage
Un polyfill (ou plutôt un ponyfill qui fournit des fonctionnalités 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 dans le 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é
Pour obtenir des conseils fiables, consultez la section correspondante du projet de spécification.
Commentaires
L'équipe Chrome souhaite connaître votre avis et votre expérience concernant cette API.
Commentaires sur la conception de l'API
Y a-t-il quelque chose dans l'API qui est maladroit ou qui ne fonctionne pas comme prévu ? Ou bien manque-t-il des éléments pour mettre en œuvre votre idée ?
Signalez un problème dans le dépôt GitHub Web Transport ou ajoutez vos commentaires à un problème existant.
Vous rencontrez un problème d'implémentation ?
Avez-vous trouvé un bug dans l'implémentation de Chrome ?
Signalez un bug sur https://new.crbug.com. Incluez autant de détails que possible, ainsi que des instructions simples pour reproduire le problème.
Vous prévoyez d'utiliser l'API ?
Votre soutien public aide Chrome à hiérarchiser les fonctionnalités et montre aux autres fournisseurs de navigateurs à quel point il est essentiel de les prendre en charge.
- Envoyez un tweet à @ChromiumDev en utilisant le hashtag
#WebTransport
et en précisant où et comment vous l'utilisez.
Discussion générale
Vous pouvez utiliser le groupe Google web-transport-dev pour les questions ou problèmes généraux qui ne correspondent à aucune des autres catégories.
Remerciements
Cet article intègre des informations provenant de l'explication de WebTransport, de la spécification provisoire et des documents de conception associés. Merci aux auteurs respectifs pour avoir fourni ces bases.
L'image principale de cet article est de Robin Pierre sur Unsplash.