Enviar datos entre dos navegadores para la comunicación, los juegos o la transferencia de archivos puede ser un proceso bastante complejo. Requiere configurar y pagar un servidor para retransmitir datos, y tal vez escalar esto a varios centros de datos. En este caso, existe la posibilidad de que haya una latencia alta y es difícil mantener la privacidad de los datos.
Estos problemas se pueden aliviar con la API de RTCDataChannel de WebRTC para transferir datos directamente de un par a otro. En este artículo, se explican los conceptos básicos para configurar y usar los canales de datos, así como los casos de uso comunes en la Web actual.
¿Por qué otro canal de datos?
Tenemos WebSocket, AJAX y Server Sent Events. ¿Por qué necesitamos otro canal de comunicación? WebSocket es bidireccional, pero todas estas tecnologías están diseñadas para la comunicación hacia o desde un servidor.
RTCDataChannel adopta un enfoque diferente:
- Funciona con la API de
RTCPeerConnection, que habilita la conectividad peer-to-peer. Esto puede generar una latencia más baja, ya que no hay un servidor intermedio y hay menos "saltos". RTCDataChannelusa el protocolo de transmisión de control de flujo (SCTP), lo que permite la semántica de entrega configurable, la entrega desordenada y la configuración de retransmisión.
RTCDataChannel ya está disponible con compatibilidad con SCTP en computadoras y Android en Google Chrome, Opera y Firefox.
Advertencia: Señalización, STUN y TURN
WebRTC permite la comunicación entre pares, pero aún necesita servidores para la señalización para intercambiar metadatos de medios y de red para iniciar una conexión entre pares.
WebRTC se enfrenta a NAT y firewalls con lo siguiente:
- El framework de ICE para establecer la mejor ruta de red posible entre pares
- Servidores STUN para determinar una IP y un puerto de acceso público para cada par
- Servidores TURN si falla la conexión directa y se requiere la retransmisión de datos
Para obtener más información sobre cómo funciona WebRTC con los servidores para la señalización y las redes, consulta WebRTC en el mundo real: STUN, TURN y señalización.
Las capacidades
La API de RTCDataChannel admite un conjunto flexible de tipos de datos. La API está diseñada para imitar WebSocket exactamente, y RTCDataChannel admite cadenas, así como algunos de los tipos binarios en JavaScript, como Blob, ArrayBuffer y ArrayBufferView. Estos tipos pueden ser útiles cuando se trabaja con la transferencia de archivos y los juegos multijugador.
RTCDataChannel puede funcionar en modo no confiable y no ordenado (análogo al protocolo de datagramas de usuario o UDP), en modo confiable y ordenado (análogo al protocolo de control de transmisión o TCP) y en modos confiables parciales:
- El modo confiable y ordenado garantiza la transmisión de mensajes y el orden en que se entregan. Esto genera una sobrecarga adicional, por lo que es posible que este modo sea más lento.
- El modo no confiable y desordenado no garantiza que todos los mensajes lleguen al otro lado ni el orden en que lo hacen. Esto elimina la sobrecarga, lo que permite que este modo funcione mucho más rápido.
- El modo confiable parcial garantiza la transmisión de mensajes en una condición específica, como un tiempo de espera de retransmisión o una cantidad máxima de retransmisiones. El orden de los mensajes también se puede configurar.
El rendimiento de los dos primeros modos es casi el mismo cuando no hay pérdidas de paquetes. Sin embargo, en el modo confiable y ordenado, un paquete perdido hace que otros paquetes queden bloqueados detrás de él, y el paquete perdido podría estar desactualizado cuando se retransmita y llegue. Por supuesto, es posible usar varios canales de datos dentro de la misma app, cada uno con su propia semántica confiable o no confiable.
Esta es una tabla útil de High Performance Browser Networking de Ilya Grigorik:
| TCP | UDP | SCTP | |
| Confiabilidad | Confiable | No confiables | Configurable |
| Entrega | Ordenado | Sin ordenar | Configurable |
| Transmisión | Orientado a bytes | Orientado a mensajes | Orientado a mensajes |
| Control de flujo | Sí | No | Sí |
| Control de congestión | Sí | No | Sí |
A continuación, aprenderás a configurar RTCDataChannel para que use el modo confiable y ordenado, o bien el modo no confiable y no ordenado.
Configura canales de datos
En línea, hay varias demostraciones sencillas de RTCDataChannel:
- simpl.info
RTCDataChannel - Muestras de WebRTC: Transmitir texto
- Muestras de WebRTC: Transfiere un archivo
En estos ejemplos, el navegador establece una conexión de par consigo mismo, luego crea un canal de datos y envía un mensaje a través de la conexión de par. Luego, crea un canal de datos y envía el mensaje a través de la conexión de pares. Por último, tu mensaje aparecerá en el cuadro del otro lado de la página.
El código para comenzar es corto:
const peerConnection = new RTCPeerConnection();
// Establish your peer connection using your signaling channel here
const dataChannel =
peerConnection.createDataChannel("myLabel", dataChannelOptions);
dataChannel.onerror = (error) => {
console.log("Data Channel Error:", error);
};
dataChannel.onmessage = (event) => {
console.log("Got Data Channel Message:", event.data);
};
dataChannel.onopen = () => {
dataChannel.send("Hello World!");
};
dataChannel.onclose = () => {
console.log("The Data Channel is Closed");
};
El objeto dataChannel se crea a partir de una conexión de pares ya establecida. Se puede crear antes o después de que se produzca la señalización. Luego, pasas una etiqueta para distinguir este canal de otros y un conjunto de parámetros de configuración opcionales:
const dataChannelOptions = {
ordered: false, // do not guarantee order
maxPacketLifeTime: 3000, // in milliseconds
};
También es posible agregar una opción maxRetransmits (la cantidad de veces que se debe intentar antes de que falle), pero solo puedes especificar maxRetransmits o maxPacketLifeTime, no ambos. Para la semántica de UDP, establece maxRetransmits en 0 y ordered en false. Para obtener más información, consulta los RFC del IETF Stream Control Transmission Protocol y Stream Control Transmission Protocol Partial Reliability Extension.
ordered: Indica si el canal de datos debe garantizar el orden o no.maxPacketLifeTime: Es el tiempo máximo para intentar retransmitir un mensaje fallido.maxRetransmits: Es la cantidad máxima de veces que se intentará retransmitir un mensaje fallido.protocol: Permite usar un subprotocolo, que proporciona metainformación a la app.negotiated: Si se configura como verdadero, quita la configuración automática de un canal de datos en el otro par, lo que te permite crear un canal de datos con el mismo ID en el otro extremo.id: Te permite proporcionar tu propio ID para el canal, que solo se puede usar en combinación connegotiatedestablecido entrue.
Las únicas opciones que la mayoría de las personas necesitan usar son las tres primeras: ordered, maxPacketLifeTime y maxRetransmits. Con SCTP (que ahora usan todos los navegadores que admiten WebRTC), la confiabilidad y el orden son verdaderos de forma predeterminada. Tiene sentido usar la opción no confiable y no ordenada si deseas tener el control total desde la capa de la app, pero, en la mayoría de los casos, la confiabilidad parcial es útil.
Ten en cuenta que, al igual que con WebSocket, RTCDataChannel activa eventos cuando se establece, se cierra o se produce un error en una conexión, y cuando recibe un mensaje del otro par.
¿Es seguro?
La encriptación es obligatoria para todos los componentes de WebRTC. Con RTCDataChannel, todos los datos están protegidos con la seguridad de la capa de transporte de datagramas (DTLS). DTLS es un derivado de SSL, lo que significa que tus datos estarán tan seguros como con cualquier conexión estándar basada en SSL. DTLS está estandarizado y se incluye en todos los navegadores que admiten WebRTC. Para obtener más información, consulta la wiki de Wireshark.
Cambia tu forma de pensar sobre los datos
Manejar grandes cantidades de datos puede ser un punto débil en JavaScript. Como señalaron los desarrolladores de Sharefest, esto requirió pensar en los datos de una manera nueva. Si transfieres un archivo más grande que la cantidad de memoria disponible, debes pensar en nuevas formas de guardar esta información. Aquí es donde entran en juego tecnologías como la API de FileSystem, como verás a continuación.
Crea una app para compartir archivos
Ahora es posible crear una app web que pueda compartir archivos en el navegador con RTCDataChannel. Crear sobre RTCDataChannel significa que los datos de los archivos transferidos están encriptados y no pasan por los servidores de un proveedor de apps. Esta funcionalidad, combinada con la posibilidad de conectarse a varios clientes para compartir archivos más rápido, hace que el uso compartido de archivos con WebRTC sea una excelente opción para la Web.
Para realizar una transferencia exitosa, se requieren varios pasos:
- Lee un archivo en JavaScript con la API de File.
- Establece una conexión de pares entre clientes con
RTCPeerConnection. - Crea un canal de datos entre clientes con
RTCDataChannel.
Hay varios puntos que debes tener en cuenta cuando intentas enviar archivos a través de RTCDataChannel:
- Tamaño del archivo: Si el tamaño del archivo es razonablemente pequeño y se puede almacenar y cargar como un solo Blob, puedes cargarlo en la memoria con la API de File y, luego, enviarlo a través de un canal confiable tal como está (aunque ten en cuenta que los navegadores imponen límites en el tamaño máximo de transferencia). A medida que el tamaño del archivo aumenta, las cosas se complican. Cuando se requiere un mecanismo de fragmentación, los fragmentos de archivos se cargan y se envían a otro par, junto con metadatos
chunkIDpara que el par pueda reconocerlos. Ten en cuenta que, en este caso, también debes guardar primero los fragmentos en el almacenamiento sin conexión (por ejemplo, con la API de FileSystem) y guardarlos en el disco del usuario solo cuando tengas el archivo completo. - Tamaño de fragmento: Son los "átomos" de datos más pequeños de tu app. El fragmentado es obligatorio porque actualmente hay un límite de tamaño de envío (aunque esto se corregirá en una versión futura de los canales de datos). La recomendación actual para el tamaño máximo de fragmento es de 64 KiB.
Una vez que el archivo se transfiera por completo al otro lado, se podrá descargar con una etiqueta de anclaje:
function saveFile(blob) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'File Name';
link.click();
};
Las apps para compartir archivos en PubShare y GitHub usan esta técnica. Ambos son de código abierto y proporcionan una buena base para una app de uso compartido de archivos basada en RTCDataChannel.
Entonces, ¿qué puedes hacer?
RTCDataChannel abre las puertas a nuevas formas de crear apps para compartir archivos, juegos multijugador y entrega de contenido.
- Compartir archivos de punto a punto, como se describió anteriormente
- Juegos multijugador, combinados con otras tecnologías, como WebGL, como se ve en BananaBread de Mozilla
- La entrega de contenido reinventada por PeerCDN, un framework que entrega recursos web a través de la comunicación de datos peer-to-peer
Cambia la forma en que compilas apps
Ahora puedes proporcionar apps más atractivas con conexiones de alto rendimiento y baja latencia a través de RTCDataChannel. Los frameworks, como PeerJS y el SDK de WebRTC de PubNub, facilitan la implementación de RTCDataChannel, y la API ahora tiene una amplia compatibilidad en todas las plataformas.
La llegada de RTCDataChannel puede cambiar la forma en que piensas sobre la transferencia de datos en el navegador.