Enviar datos entre dos navegadores para la comunicación, los videojuegos o la transferencia de archivos puede ser un proceso bastante complicado. Requiere configurar y pagar por un servidor que retransmita datos, y quizás escalarlo a varios centros de datos. En esta situación, existe el potencial de una latencia alta y es difícil mantener la privacidad de los datos.
Estos problemas se pueden aliviar con el uso de la API de RTCDataChannel
de WebRTC para transferir datos directamente de un par a otro. En este artículo, se describen los aspectos básicos de cómo configurar y usar canales de datos, así como los casos de uso comunes en la Web en la actualidad.
¿Por qué usar otro canal de datos?
Tenemos WebSocket, AJAX y eventos enviados por el servidor. ¿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 entre pares. Esto puede generar una latencia más baja, sin un servidor intermediario y menos “saltos”. RTCDataChannel
usa el protocolo de transmisión de control de transmisión (SCTP), lo que permite la configuración configurable de entrega y retransmisión de semántica de entrega desordenada.
RTCDataChannel
ahora está disponible con compatibilidad con SCTP en computadoras de escritorio y Android en Google Chrome, Opera y Firefox.
Una advertencia: señalización, STUN y TURN
WebRTC habilita la comunicación entre pares, pero aún necesita servidores para la señalización para intercambiar metadatos de red y multimedia para iniciar una conexión de par.
WebRTC se adapta a las NAT y los firewalls con lo siguiente:
- El framework ICE para establecer la mejor ruta de red posible entre los pares.
- Servidores STUN para determinar una IP y un puerto de acceso público para cada intercambio de tráfico.
- Servidores TURN si la conexión directa falla y se requiere la retransmisión de datos.
Si deseas obtener más información sobre cómo funciona WebRTC con los servidores para la señalización y las herramientas de redes, consulta WebRTC en el mundo real: STUN, TURN, y la señalización.
Las capacidades
La API de RTCDataChannel
admite un conjunto flexible de tipos de datos. La API está diseñada para imitar exactamente WebSocket, y RTCDataChannel
admite cadenas, al igual que algunos tipos de objetos binarios en JavaScript, como Blob, ArrayBuffer y ArrayBufferView. Estos tipos pueden ser útiles cuando trabajas con transferencias de archivos y juegos multijugador.
RTCDataChannel
puede funcionar en modo no confiable y desordenado (análogo al protocolo de datagramas de usuario o UDP), modo confiable y ordenado (análogo al protocolo de control de transmisión o TCP) y modos confiables parciales:
- El modo confiable y ordenado garantiza la transmisión de mensajes y también el orden en que se entregan. Esto genera una sobrecarga adicional, lo que podría ralentizar este modo.
- El modo no confiable y no ordenado no garantiza que todos los mensajes lleguen al otro extremo ni en qué orden. Esto quita 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 condiciones específicas, 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 aproximadamente el mismo cuando no hay pérdidas de paquetes. Sin embargo, en el modo confiable y ordenado, un paquete perdido hace que otros paquetes se bloqueen detrás de él, y el paquete perdido puede estar inactivo cuando se retransmite y llega. Por supuesto, es posible usar varios canales de datos dentro de la misma app, cada uno con su propia semántica confiable o poco confiable.
Esta es una tabla útil de Herramientas de redes de navegador de alto rendimiento de Ilya Grigorik:
TCP | UDP | SCTP | |
Confiabilidad | Confiable | No confiables | Configurable |
Entrega | Ordenado | Sin orden | Configurable |
Transmisión | Orientada a bytes | Orientado a los mensajes | Orientado a los mensajes |
Control de flujo | Sí | No | Sí |
Control de la congestión | Sí | No | Sí |
A continuación, aprenderás a configurar RTCDataChannel
para usar el modo confiable y ordenado o no confiable y no ordenado.
Configura canales de datos
Hay varias demostraciones simples de RTCDataChannel
en línea:
- simpl.info
RTCDataChannel
- Muestras de WebRTC Transmite texto
- Muestras de WebRTC: Cómo transferir un archivo
En estos ejemplos, el navegador establece una conexión de par consigo mismo y, luego, crea un canal de datos y envía un mensaje a través de la conexión de par. A continuación, crea un canal de datos y envía el mensaje a través de la conexión de intercambio de tráfico. Por último, tu mensaje aparece en el cuadro que está al otro lado de la página.
El código para comenzar con esto es breve:
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 el indicador. Luego, pasas una etiqueta para distinguir este canal de los demás 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 estas RFC de IETF: Protocolo de transmisión de control de flujo y Extensión de confiabilidad parcial del protocolo de transmisión de control de flujo.
ordered
: Indica si el canal de datos debe garantizar o no el orden.maxPacketLifeTime
: El tiempo máximo para intentar retransmitir un mensaje con erroresmaxRetransmits
: Es la cantidad máxima de veces que se intentará retransmitir un mensaje con errores.protocol
: Permite usar un subprotocolo, que proporciona metainformación a la app.negotiated
: Si se establece como verdadero, quita la configuración automática de un canal de datos en el otro par y te proporciona tu propia forma de 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 connegotiated
establecido entrue
.
Las únicas opciones que la mayoría de las personas deben 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 no confiable y no ordenado si deseas tener 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, cierra o genera errores 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). El 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. El DTLS está estandarizado y está integrado 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
El manejo de grandes cantidades de datos puede ser un problema en JavaScript. Como señalaron los desarrolladores de Sharefest, esto requirió pensar en los datos de una manera nueva. Si vas a transferir un archivo que supera 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.
Compila una app para compartir archivos
Con RTCDataChannel
, ahora es posible crear una app web que pueda compartir archivos en el navegador. Compilar en RTCDataChannel
significa que los datos de archivos transferidos están encriptados y no tocan 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 de WebRTC sea una opción sólida para la Web.
Se deben seguir varios pasos para que la transferencia se realice correctamente:
- Lee un archivo en JavaScript con la API de File.
- Realiza una conexión entre 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 bastante 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 tal como está a través de un canal confiable (aunque ten en cuenta que los navegadores imponen límites en el tamaño máximo de transferencia). A medida que aumenta el tamaño de los archivos, todo se complica. Cuando se requiere un mecanismo de fragmentación, los bloques de archivos se cargan y se envían a otro par, junto con los metadatos
chunkID
para que el par pueda reconocerlos. Ten en cuenta que, en este caso, primero debes guardar 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 del segmento: Son los “átomos” de datos más pequeños para tu app. La fragmentación es obligatoria porque actualmente hay un límite de tamaño de envío (aunque 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 puede descargar con una etiqueta de ancla:
function saveFile(blob) {
const link = document.createElement('a');
link.href = window.URL.createObjectURL(blob);
link.download = 'File Name';
link.click();
};
Estas apps de uso compartido de 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 compilar apps para compartir archivos, juegos multijugador y entrega de contenido.
- Uso compartido de archivos entre pares, como se describió anteriormente
- Juegos multijugador combinados con otras tecnologías, como WebGL, como se ve en BananaBread de Mozilla
- La entrega de contenido se reinventó con PeerCDN, un framework que entrega recursos web a través de la comunicación de datos entre pares.
Cambia tu forma de compilar 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 es compatible con todas las plataformas.
La llegada de RTCDataChannel
puede cambiar la forma en que piensas sobre la transferencia de datos en el navegador.