WebTransport es una API que ofrece mensajería bidireccional cliente-servidor de baja latencia. Obtén más información sobre sus casos de uso y cómo enviar comentarios sobre el futuro de la implementación.
Información general
¿Qué es WebTransport?
WebTransport es una API web que usa el protocolo HTTP/3 como transporte bidireccional. Está diseñado para las comunicaciones bidireccionales entre un cliente web y un servidor HTTP/3. Admite el envío de datos de manera poco confiable a través de sus APIs de datagrama y de manera confiable a través de sus APIs de transmisión.
Los datagramas son ideales para enviar y recibir datos que no necesitan garantías de entrega sólidas. La unidad de transmisión máxima (MTU) de la conexión subyacente limita el tamaño de los paquetes de datos individuales y pueden o no transmitirse correctamente. Si se transfieren, pueden llegar en un orden arbitrario. Estas características hacen que las APIs de datagramas sean ideales para la transmisión de datos de baja latencia y el mejor esfuerzo. Puedes pensar en los datagramas como mensajes de protocolo de datagramas de usuario (UDP), pero encriptados y controlados por la congestión.
En cambio, las APIs de transmisiones ofrecen una transferencia de datos confiable y ordenada. Son adecuados para situaciones en las que necesitas enviar o recibir una o más transmisiones de datos ordenados. El uso de varias transmisiones de WebTransport es similar al establecimiento de múltiples conexiones TCP, pero, como HTTP/3 usa el protocolo QUIC más liviano, se pueden abrir y cerrar sin tanta sobrecarga.
Casos de uso
Esta es una pequeña lista de las posibles formas en que los desarrolladores podrían usar WebTransport.
- Envío del estado del juego a intervalos regulares con latencia mínima a un servidor a través de mensajes pequeños, poco confiables y desordenados.
- Recibir transmisiones de contenido multimedia enviadas desde un servidor con una latencia mínima, independiente de otras transmisiones de datos
- Recibir notificaciones enviadas desde un servidor mientras una página web está abierta.
Nos gustaría obtener más información sobre cómo planeas usar WebTransport.
Navegadores compatibles
Al igual que con todas las funciones que no cuentan con compatibilidad universal para los navegadores, se recomienda programar de forma defensiva mediante la detección de funciones.
Estado actual
Paso | Estado |
---|---|
1. Crear explicación | Completo |
2. Crea el borrador inicial de la especificación | Completo |
3. Recopilación de comentarios y diseño de iteraciones | Completado |
4. Prueba de origen | Completado |
5. Lanzamiento | Chromium 97 |
Relación de WebTransport con otras tecnologías
¿WebTransport es un reemplazo de WebSockets?
Tal vez. Hay casos de uso en los que WebSockets o WebTransport pueden ser protocolos de comunicación válidos para usar.
Las comunicaciones de WebSockets se modelan en torno a un flujo de mensajes único, confiable y ordenado, lo cual está bien para algunos tipos de necesidades de comunicación. Si necesitas esas características, las APIs de transmisión de WebTransport también pueden proporcionarlas. En comparación, las APIs de datagramas de WebTransport proporcionan una entrega de latencia baja, sin garantías sobre la confiabilidad ni el orden, por lo que no son un reemplazo directo de WebSockets.
El uso de WebTransport, a través de las APIs de datagramas o a través de varias instancias simultáneas de la API de Streams, significa que no tienes que preocuparte por el bloqueo de la cabeza de línea, lo que puede ser un problema con WebSockets. Además, existen beneficios de rendimiento cuando se establecen conexiones nuevas, ya que el protocolo de enlace QUIC subyacente es más rápido que iniciar TCP por TLS.
WebTransport es parte de una nueva especificación en borrador y, como tal, el ecosistema de WebSocket en torno a las bibliotecas cliente y de servidor es actualmente mucho más sólido. Si necesitas algo que funcione de inmediato con configuraciones de servidor comunes y una amplia compatibilidad con clientes web, WebSockets es una mejor opción hoy en día.
¿WebTransport es lo mismo que una API de UDP Socket?
No. WebTransport no es una API de UDP Socket. Mientras que WebTransport usa HTTP/3, que a su vez usa UDP “de forma interna”, WebTransport tiene requisitos sobre la encriptación y el control de la congestión que la convierten en algo más que una API básica de UDP Socket.
¿WebTransport es una alternativa a los canales de datos de WebRTC?
Sí, para conexiones cliente-servidor. WebTransport comparte muchas de las mismas propiedades que los canales de datos de WebRTC, aunque los protocolos subyacentes son diferentes.
Por lo general, ejecutar un servidor compatible con HTTP/3 requiere menos configuración que mantener un servidor WebRTC, lo que implica comprender varios protocolos (ICE, DTLS y SCTP) para lograr un transporte adecuado. WebRTC implica muchos más elementos en movimiento que podrían provocar fallas en las negociaciones entre el cliente y el servidor.
La API de WebTransport se diseñó teniendo en cuenta los casos de uso de desarrolladores web, y debería parecerse más a escribir un código de plataforma web moderna que a usar interfaces de canal de datos de WebRTC. A diferencia de WebRTC, WebTransport es compatible con los Trabajadores web, lo que te permite realizar comunicaciones cliente-servidor independientemente de una página HTML determinada. Debido a que WebTransport expone una interfaz que cumple con Streams, admite optimizaciones en torno a la contrapresión.
Sin embargo, si ya tienes una configuración de cliente/servidor de WebRTC que funcione y te resulta satisfactoria, es posible que cambiar a WebTransport no te ofrezca muchas ventajas.
Probar
La mejor manera de experimentar con WebTransport es iniciar un servidor HTTP/3 compatible. Luego, podrás usar esta página con un cliente de JavaScript básico para probar la comunicación entre el cliente y el servidor.
Además, hay disponible un servidor de eco mantenido por la comunidad en webtransport.day.
Cómo usar la API
WebTransport se diseñó a partir de las primitivas de las plataformas web modernas, como la API de Streams. Se basa en gran medida en las promesas y funciona bien con async
y await
.
La implementación actual de WebTransport en Chromium admite tres tipos distintos de tráfico: datagramas, así como transmisiones unidireccionales y bidireccionales.
Conexión con un servidor
Puedes conectarte a un servidor HTTP/3 si creas una instancia de WebTransport
. El esquema de la URL debe ser https
. Debes especificar de forma explícita el número de puerto.
Debes usar la promesa ready
para esperar a que se establezca la conexión. Esta promesa no se cumplirá hasta que se complete la configuración y se rechazará si la conexión falla en la etapa de QUIC/TLS.
La promesa closed
se cumple cuando la conexión se cierra normalmente y se rechaza si el cierre fue inesperado.
Si el servidor rechaza la conexión debido a un error de indicación de cliente (p.ej., la ruta de la URL no es válida), se rechaza closed
, mientras que ready
no se resuelve.
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 datagramas
Una vez que tengas una instancia de WebTransport que esté conectada a un servidor, puedes usarla para enviar y recibir bits de datos discretos, conocidos como datagramas.
El método get writeable
muestra un WritableStream
, que un cliente web puede usar para enviar datos al servidor. El método get readable
muestra un ReadableStream
, lo que te permite escuchar los datos del servidor. Ambas transmisiones son intrínsecamente poco confiables, de modo que es posible que el servidor no reciba los datos que escribas, y viceversa.
Ambos tipos de transmisiones usan instancias de Uint8Array
para la transferencia de datos.
// 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);
}
APIs de Streams
Una vez que te hayas conectado al servidor, también puedes usar WebTransport para enviar y recibir datos a través de sus APIs de Streams.
Cada fragmento de todas las transmisiones es un Uint8Array
. A diferencia de las APIs de Datagram, estas transmisiones son confiables. Sin embargo, cada transmisión es independiente, por lo que no se garantiza el orden de los datos entre las transmisiones.
WebTransportSendStream
El cliente web crea un WebTransportSendStream
con el método createUnidirectionalStream()
de una instancia de WebTransport
, que muestra una promesa para el WebTransportSendStream
.
Usa el método close()
de WritableStreamDefaultWriter
para cerrar la conexión HTTP/3 asociada. El navegador intenta enviar todos los datos pendientes antes de cerrar la conexión asociada.
// 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 manera similar, usa el método abort()
de WritableStreamDefaultWriter
para enviar un RESET\_STREAM
al servidor. Cuando se usa abort()
, es posible que el navegador descarte los datos pendientes que aún no se enviaron.
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
El servidor inicia un WebTransportReceiveStream
. La obtención de un WebTransportReceiveStream
es un proceso de dos pasos para un cliente web. Primero, llama al atributo incomingUnidirectionalStreams
de una instancia de WebTransport
, que muestra un ReadableStream
. Cada fragmento de ese ReadableStream
es, a su vez, un WebTransportReceiveStream
que se puede usar para leer instancias de Uint8Array
enviadas por el servidor.
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);
}
Puedes detectar el cierre de la transmisión con la promesa closed
de ReadableStreamDefaultReader
. Cuando la conexión HTTP/3 subyacente se cierra con el bit FIN, la promesa closed
se cumple después de que se leen todos los datos. Cuando la conexión HTTP/3 se cierra de forma abrupta (por ejemplo, con RESET\_STREAM
), se rechaza la promesa closed
.
// 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
El servidor o el cliente pueden crear un WebTransportBidirectionalStream
.
Los clientes web pueden crear una con el método createBidirectionalStream()
de una instancia de WebTransport
, que muestra una promesa para WebTransportBidirectionalStream
.
const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream
Puedes escuchar un WebTransportBidirectionalStream
creado por el servidor con el atributo incomingBidirectionalStreams
de una instancia WebTransport
, que muestra un ReadableStream
. Cada parte de ese ReadableStream
es, a su vez, 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
es solo una combinación de WebTransportSendStream
y WebTransportReceiveStream
. En los ejemplos de las dos secciones anteriores, se explica cómo usar cada una de ellas.
Más ejemplos
La especificación de borrador de WebTransport incluye una serie de ejemplos intercalados adicionales, junto con documentación completa de todos los métodos y propiedades.
WebTransport en Herramientas para desarrolladores de Chrome
Lamentablemente, las Herramientas para desarrolladores de Chrome no son compatibles actualmente con WebTransport. Puedes “destacar” este problema de Chrome para recibir notificaciones sobre actualizaciones en la interfaz de Herramientas para desarrolladores.
Polyfill
Un polyfill (o "ponyfill" que proporciona funcionalidad como módulo independiente que puedes usar) llamado
webtransport-ponyfill-websocket
que implementa algunas de las funciones de WebTransport está disponible. Lee con atención las restricciones de
el README
del proyecto a fin de determinar si esta solución puede funcionar para tu caso de uso.
Consideraciones de privacidad y seguridad
Consulta la sección correspondiente de la especificación de borrador para obtener orientación autorizada.
Comentarios
El equipo de Chrome quiere conocer tus opiniones y experiencias con esta API.
Comentarios sobre el diseño de la API
¿Hay algo en la API que sea incómodo o que no funcione como se esperaba? ¿O faltan partes que necesitas para implementar tu idea?
Informa sobre un problema en el repositorio de GitHub de Web Transport o agrega tus opiniones sobre un problema existente.
¿Tiene problemas con la implementación?
¿Encontraste un error en la implementación de Chrome?
Informa un error en https://new.crbug.com. Incluye tantos detalles como sea posible, junto con instrucciones sencillas para la reproducción.
¿Piensas usar la API?
Tu asistencia pública ayuda a Chrome a priorizar funciones y les muestra a otros proveedores de navegadores la importancia de brindar compatibilidad con ellas.
- Envía un tweet a @ChromiumDev con el hashtag
#WebTransport
y detalles sobre dónde y cómo lo utilizas.
Debate general
Puedes usar el Grupo de Google web-transport-dev para resolver problemas o preguntas generales que no correspondan a ninguna de las otras categorías.
Agradecimientos
Este artículo incorpora información de la explicación de WebTransport, la especificación de borrador y los documentos de diseño relacionados. Gracias a los respectivos autores por proporcionar esa base.
La imagen hero de esta publicación es de Robin Pierre en Unsplash.