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.
Fondo
¿Qué es WebTransport?
WebTransport es una API web que usa el protocolo HTTP/3 como transporte bidireccional. Está diseñado para comunicaciones bidireccionales entre un cliente web y un servidor HTTP/3. Admite el envío de datos de forma no confiable a través de sus APIs de datagramas y de forma confiable a través de sus APIs de transmisiones.
Los datagramas son ideales para enviar y recibir datos que no necesitan garantías de entrega sólidas. El tamaño de los paquetes de datos individuales está limitado por la unidad máxima de transmisión (MTU) de la conexión subyacente, y es posible que se transmitan correctamente o no, y, 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 con mejor esfuerzo y baja latencia. Puedes considerar los datagramas como mensajes del protocolo de datagramas de usuario (UDP), pero encriptados y con control de congestión.
En cambio, las APIs de transmisión proporcionan una transferencia de datos confiable y ordenada. Son adecuados para situaciones en las que necesitas enviar o recibir uno o más flujos de datos ordenados. Usar varios flujos de WebTransport es análogo a establecer varias conexiones TCP, pero, dado que HTTP/3 usa el protocolo QUIC más liviano en segundo plano, 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.
- Enviar el estado del juego a intervalos regulares con una latencia mínima a un servidor a través de mensajes pequeños, poco confiables y desordenados
- Recibir transmisiones de medios enviadas desde un servidor con una latencia mínima, independientemente de otras transmisiones de datos
- Recibir notificaciones enviadas desde un servidor mientras una página web está abierta
Nos interesa saber más sobre cómo planeas usar WebTransport.
Navegadores compatibles
Al igual que con todas las funciones que no tienen compatibilidad universal con los navegadores, la codificación defensiva a través de la detección de funciones es una práctica recomendada.
Estado actual
Paso | Estado |
---|---|
1. Crea una explicación | Completar |
2. Crea el borrador inicial de la especificación | Completar |
3. Recopila comentarios y realiza iteraciones en el diseño | Completado |
4. Prueba de origen | Completado |
5. Lanzamiento | Chromium 97 |
Relación de WebTransport con otras tecnologías
¿WebTransport reemplaza a WebSockets?
Tal vez. Existen casos de uso en los que WebSockets o WebTransport podrían ser protocolos de comunicación válidos para usar.
Las comunicaciones de WebSockets se modelan en torno a un flujo único, confiable y ordenado de mensajes, lo que es adecuado para algunos tipos de necesidades de comunicación. Si necesitas esas características, las APIs de Streams de WebTransport también pueden proporcionarlas. En comparación, las APIs de datagramas de WebTransport proporcionan una entrega de baja latencia, sin garantías sobre la confiabilidad o el orden, por lo que no son un reemplazo directo de WebSockets.
Usar WebTransport, ya sea a través de las APIs de datagramas o de varias instancias simultáneas de la API de Streams, significa que no tienes que preocuparte por el bloqueo de cabeza de línea, que puede ser un problema con WebSockets. Además, establecer conexiones nuevas ofrece beneficios de rendimiento, ya que el protocolo de enlace QUIC subyacente es más rápido que iniciar TCP a través de TLS.
WebTransport forma parte de un nuevo borrador de especificación y, como tal, el ecosistema de WebSocket en torno a las bibliotecas de cliente y servidor es mucho más sólido en la actualidad. Si necesitas algo que funcione "de inmediato" con configuraciones de servidor comunes y con una amplia compatibilidad con clientes web, WebSockets es una mejor opción hoy en día.
¿WebTransport es lo mismo que una API de socket UDP?
No. WebTransport no es una API de socket UDP. Si bien WebTransport usa HTTP/3, que a su vez usa UDP "bajo el capó", WebTransport tiene requisitos en torno a la encriptación y el control de congestión que lo convierten en algo más que una API de socket UDP básica.
¿WebTransport es una alternativa a los canales de datos de WebRTC?
Sí, para las conexiones cliente-servidor. WebTransport comparte muchas de las mismas propiedades que los canales de datos de WebRTC, aunque los protocolos subyacentes son diferentes.
En 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 obtener un transporte en funcionamiento. WebRTC implica muchas más partes móviles que podrían generar negociaciones fallidas entre el cliente y el servidor.
La API de WebTransport se diseñó teniendo en cuenta los casos de uso de los desarrolladores web y debería sentirse más como escribir código moderno de la plataforma web que usar las interfaces de canal de datos de WebRTC. A diferencia de WebRTC, WebTransport se admite dentro de los Web Workers, lo que te permite realizar comunicaciones cliente-servidor independientemente de una página HTML determinada. Dado que WebTransport expone una interfaz compatible con Streams, admite optimizaciones en torno a la contrapresión.
Sin embargo, si ya tienes una configuración de cliente/servidor de WebRTC que funciona y con la que te sientes a gusto, cambiar a WebTransport puede no ofrecer muchas ventajas.
Probar
La mejor manera de experimentar con WebTransport es iniciar un servidor HTTP/3 compatible. Luego, puedes usar esta página con un cliente básico de JavaScript para probar las comunicaciones cliente/servidor.
Además, hay un servidor de eco mantenido por la comunidad disponible en webtransport.day.
Usa la API
WebTransport se diseñó sobre la base de elementos primitivos modernos de la plataforma web, como la API de Streams. Se basa en gran medida en promesas y funciona bien con async
y await
.
La implementación actual de WebTransport en Chromium admite tres tipos distintos de tráfico: datagramas y transmisiones unidireccionales y bidireccionales.
Conexión con un servidor
Puedes conectarte a un servidor HTTP/3 creando una instancia de WebTransport
. El esquema de la URL debe ser https
. Debes especificar explícitamente 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 del cliente (p.ej., la ruta de acceso de la URL no es válida), se produce un rechazo de closed
, mientras que ready
permanece sin resolver.
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;
APIs de datagramas
Una vez que tengas una instancia de WebTransport conectada a un servidor, podrás usarla para enviar y recibir bits discretos de datos, conocidos como datagramas.
El getter writeable
devuelve un WritableStream
, que un cliente web puede usar para enviar datos al servidor. El método get readable
devuelve un ReadableStream
, lo que te permite escuchar los datos del servidor. Ambos flujos son inherentemente poco confiables, por lo 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);
}
getReader()
combinado con un bucle while()
es la mejor manera de leer desde la transmisión.
APIs de Streams
Una vez que te conectes al servidor, también podrás 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 datagramas, estos flujos 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 objeto WebTransportSendStream
con el método createUnidirectionalStream()
de una instancia WebTransport
, que devuelve una promesa para el objeto WebTransportSendStream
.
Usa el método close()
de WritableStreamDefaultWriter
para cerrar el flujo de HTTP/3 asociado. El navegador intenta enviar todos los datos pendientes antes de cerrar el flujo asociado.
// 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}`);
}
Del mismo modo, 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
. Obtener un WebTransportReceiveStream
es un proceso de dos pasos para un cliente web. Primero, llama al atributo incomingUnidirectionalStreams
de una instancia WebTransport
, que devuelve 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 el flujo subyacente de HTTP/3 se cierra con el bit FIN, la promesa de closed
se cumple después de que se leen todos los datos. Cuando el flujo de HTTP/3 se cierra de forma abrupta (por ejemplo, con RESET_STREAM
), la promesa de closed
se rechaza.
// 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
puede ser creado por el servidor o el cliente.
Los clientes web pueden crear uno con el método createBidirectionalStream()
de una instancia de WebTransport
, que devuelve una promesa para un 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 de WebTransport
, que devuelve un ReadableStream
. Cada fragmento 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 un WebTransportSendStream
y un WebTransportReceiveStream
. En los ejemplos de las dos secciones anteriores, se explica cómo usar cada uno de ellos.
Más ejemplos
La especificación preliminar de WebTransport incluye varios ejemplos intercalados adicionales, junto con la documentación completa de todos los métodos y propiedades.
WebTransport en las Herramientas para desarrolladores de Chrome
Lamentablemente, las Herramientas para desarrolladores de Chrome no admiten WebTransport en este momento. Puedes destacar este problema de Chrome para recibir notificaciones sobre las actualizaciones de la interfaz de Herramientas para desarrolladores.
Polyfill
Hay disponible un polyfill (o más bien un ponyfill que proporciona funcionalidad como un módulo independiente que puedes usar) llamado webtransport-ponyfill-websocket
que implementa algunas de las funciones de WebTransport. Lee atentamente las restricciones en el README
del proyecto para 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 del borrador para obtener orientación oficial.
Comentarios
Al equipo de Chrome le gustaría 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 no funcione como se espera? ¿O faltan piezas que necesitas para implementar tu idea?
Informa un problema en el repositorio de GitHub de Web Transport o agrega tus ideas a un problema existente.
¿Tienes 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 puedas, junto con instrucciones sencillas para reproducir el problema.
¿Planeas usar la API?
Tu apoyo público ayuda a Chrome a priorizar funciones y muestra a otros proveedores de navegadores lo importante que es admitirlas.
- Envía un tweet a @ChromiumDev con el hashtag
#WebTransport
y detalles sobre dónde y cómo lo usas.
Debate general
Puedes usar el grupo de Google web-transport-dev para preguntas o problemas generales que no se ajusten a ninguna de las otras categorías.
Agradecimientos
En este artículo, se incluye información del Explicador de WebTransport, la especificación de borrador y los documentos de diseño relacionados. Agradecemos a los autores respectivos por proporcionar esa base.
La imagen de encabezado de esta publicación es de Robin Pierre en Unsplash.