Signaling Server — es un componente servidor de la infraestructura WebRTC que facilita el intercambio de metadatos entre pares para establecer y finalizar una conexión. A diferencia del tráfico multimedia, la señalización puede transmitirse a través de cualquier protocolo — WebSocket, HTTP, XMPP o SIP. Según MDN Web Docs, 2024, la señalización es un componente obligatorio de cualquier aplicación WebRTC, ya que el protocolo no define un método específico para intercambiar mensajes de señalización.
Puntos clave
Signaling Server — es un servicio de red responsable de coordinar el proceso de establecimiento de una conexión WebRTC entre dos o más pares. No transmite datos multimedia (audio, vídeo, datos de DataChannel), solo la información de control necesaria para el descubrimiento de pares y la negociación de parámetros de conexión. Una vez establecido con éxito un canal P2P, es posible que el Signaling Server ya no sea necesario, pero en algunas arquitecturas permanece para el posterior intercambio de señales (por ejemplo, finalización de llamada, adición de participantes).
La arquitectura de señalización incluye tres componentes: Signaling Server, Signal Channel (protocolo de transporte entre cliente y servidor) y API de cliente (generalmente integrada en el stack WebRTC del navegador). La especificación WebRTC (W3C, 2024) intencionalmente no estandariza el protocolo de señalización — los desarrolladores pueden elegir cualquier transporte adecuado para su aplicación. Este enfoque flexible permite usar WebSocket para aplicaciones web, XMPP para sistemas de chat o SIP para integración con infraestructura de telecomunicaciones.
Antes de establecer una conexión WebRTC, los pares deben intercambiar tres tipos de mensajes: descripciones de sesión (offer y answer), candidatos ICE e información de finalización/modificación de sesión. El Signaling Server enruta estos mensajes entre los pares utilizando identificadores de sala o de usuario para el direccionamiento. El patrón estándar es crear una “sala” donde se conectan dos participantes, y el servidor retransmite los mensajes de cada participante solo a su interlocutor.
Signaling Server implementa el siguiente protocolo típico de establecimiento de conexión WebRTC. Los pares se conectan al servidor a través de WebSocket (u otro transporte) y se registran en una sala. El Par A (iniciador) crea una oferta (descripción SDP del flujo multimedia saliente) a través de RTCPeerConnection.createOffer(), la establece como descripción local y la envía al Signaling Server. El servidor retransmite la oferta al Par B. El Par B recibe la oferta, la establece como descripción remota, crea una respuesta a través de createAnswer(), la establece como descripción local y la envía de vuelta a través del servidor. Este proceso se llama SDP Offer/Answer.
En paralelo con el intercambio SDP, cada par recopila candidatos ICE (host, srflx, relay) y los envía a través del Signaling Server al otro par. El par remoto agrega los candidatos recibidos a través de RTCPeerConnection.addIceCandidate(). El proceso ICE prueba todas las combinaciones de candidatos para encontrar una ruta funcional. Una vez que se encuentra una ruta funcional (generalmente en 1–5 segundos), el tráfico multimedia comienza a fluir directamente entre los pares, y el Signaling Server ya no participa en la transmisión de datos — su rol termina hasta el próximo evento de control (finalización de llamada, cambio de calidad de flujo).
Para el direccionamiento de mensajes, el Signaling Server utiliza un mecanismo de salas (rooms) o canales. Cada nueva sesión WebRTC crea una sala única con un identificador (generalmente UUID). El iniciador crea la sala y espera la conexión del segundo par. El segundo par se une a la sala usando el ID recibido a través de un canal externo (por ejemplo, un enlace de invitación). El servidor mantiene un mapa de salas, donde cada ID corresponde a una lista de clientes conectados. Cuando el número de participantes alcanza dos, el servidor comienza a retransmitir mensajes de señalización entre ellos.
Signaling Server puede usar diferentes protocolos de transporte, cada uno con sus propias ventajas y desventajas. La elección del protocolo depende del tipo de aplicación, las restricciones de infraestructura y los requisitos de compatibilidad. A continuación se muestran los protocolos más comunes y sus características.
| Protocolo | Transporte | Ventajas | Desventajas |
|---|---|---|---|
| WebSocket | TCP | Dúplex completo, baja latencia, integrado en navegadores | Complejidad de escalado, bloqueo de proxy |
| HTTP/SSE | TCP | Compatible con cualquier infraestructura, simple de implementar | Solo unidireccional (servidor-cliente), requiere Polling |
| XMPP | TCP | Estandarizado, soporte de autenticación, extensible | Excesivo para escenarios simples, sobrecarga XML |
| SIP | UDP/TCP | Integración con infraestructura VoIP y telefónica | Complejo, no nativo para navegadores |
| MQTT | TCP | Ligero, funciona en entornos IoT, publish/subscribe | Requiere un broker, latencia adicional |
WebSocket es el protocolo más popular para Signaling Server en aplicaciones web. Proporciona comunicación full-dúplex, lo cual es importante para el intercambio asíncrono de candidatos SDP e ICE, y es compatible de forma nativa con todos los navegadores modernos a través de la API WebSocket. Las implementaciones de servidor WebSocket están disponibles en todas las plataformas populares (Node.js, Python, Java, Go). Para aplicaciones con millones de usuarios, se utilizan soluciones WebSocket escalables basadas en Redis Pub/Sub o Kafka para sincronizar entre instancias de Signaling Server.
Veamos una implementación simple de Signaling Server en Node.js usando la biblioteca ws (WebSocket) y el servidor HTTP incorporado. El servidor admite registro de usuarios, creación de salas y retransmisión de mensajes entre participantes.
const WebSocket = require("ws");
const server = new WebSocket.Server({ port: 8080 });
const rooms = new Map();
server.on("connection", (ws) => {
ws.roomId = null;
ws.on("message", (data) => {
const msg = JSON.parse(data);
switch (msg.type) {
case "join":
handleJoin(ws, msg.roomId);
break;
case "offer":
case "answer":
case "ice-candidate":
relayToPeer(ws, msg);
break;
case "leave":
handleLeave(ws);
break;
}
});
ws.on("close", () => handleLeave(ws));
});
function handleJoin(ws, roomId) {
if (!rooms.has(roomId)) {
rooms.set(roomId, []);
}
const room = rooms.get(roomId);
room.push(ws);
ws.roomId = roomId;
if (room.length === 2) {
room[0].send(JSON.stringify({ type: "peer-joined" }));
room[1].send(JSON.stringify({ type: "peer-joined" }));
}
}
function relayToPeer(sender, msg) {
const room = rooms.get(sender.roomId);
if (!room) return;
room.forEach(peer => {
if (peer !== sender && peer.readyState === WebSocket.OPEN) {
peer.send(JSON.stringify(msg));
}
});
}
function handleLeave(ws) {
if (!ws.roomId) return;
const room = rooms.get(ws.roomId);
if (!room) return;
const idx = room.indexOf(ws);
if (idx !== -1) room.splice(idx, 1);
if (room.length === 0) rooms.delete(ws.roomId);
}
Este Signaling Server implementa la funcionalidad básica: conexión a una sala, retransmisión de mensajes WebRTC (offer, answer, ice-candidate) entre dos pares y gestión de desconexiones. El servidor usa un Map para almacenar salas con clientes WebSocket conectados. La función relayToPeer envía un mensaje a todos los participantes de la sala excepto al remitente. Para producción, necesitará agregar validación de tipos de mensajes, manejo de errores de análisis JSON y un mecanismo heartbeat para detectar conexiones rotas.
En el lado del cliente, el Signaling Server se integra a través de la API WebSocket del navegador. El cliente establece una conexión con el servidor, envía una solicitud para unirse a una sala y luego procesa los mensajes WebRTC entrantes, pasándolos a RTCPeerConnection a través de setRemoteDescription() y addIceCandidate(). El código del cliente también envía sus propios candidatos SDP e ICE al servidor, obtenidos de RTCPeerConnection a través del evento onicecandidate y después de crear la oferta/respuesta.
Signaling Server transmite dos tipos clave de metadatos: SDP (Session Description Protocol) y candidatos ICE. SDP describe los parámetros del flujo multimedia — códecs, frecuencia de muestreo, número de canales, dirección de transmisión (sendrecv, sendonly, recvonly, inactive). Los candidatos ICE contienen direcciones de red (locales, obtenidas de STUN, relay de TURN) a través de las cuales un par puede ser alcanzado para la conexión.
SDP se presenta en un formato de texto que contiene secciones de sesión y de medios. La parte de sesión describe parámetros generales (ID de sesión, versión, nombre), mientras que las secciones de medios describen cada flujo multimedia (audio, vídeo, DataChannel) con su códec, puerto y protocolo. Los candidatos ICE contienen foundation (identificador de agrupación), prioridad, dirección IP, puerto, tipo (host, srflx, relay) y protocolo (UDP, TCP). Cada candidato también incluye un atributo ufrag (username fragment) que lo vincula a un proceso ICE específico.
Trickle ICE acelera significativamente el establecimiento de la conexión WebRTC. En lugar de esperar la recopilación completa de todos los candidatos ICE (que puede tomar 2–10 segundos en redes complejas), cada candidato se envía al Signaling Server inmediatamente después de su descubrimiento. El par remoto recibe el candidato e inmediatamente comienza la prueba de conexión a través del framework ICE. Esto reduce el tiempo de establecimiento de la conexión a 500–1500 ms en la mayoría de los casos.
Preguntas frecuentes
Signaling Server — es el “coordinador” antes de una llamada. Ayuda a dos dispositivos a encontrarse y acordar cómo se comunicarán. Una vez que los dispositivos se han “conocido” y acordado, el servidor ya no es necesario — se comunican directamente.
WebRTC no define un protocolo de señalización para que los desarrolladores puedan elegir el transporte más adecuado. El navegador no tiene un mecanismo integrado para descubrir otros usuarios — esta tarea la realiza el Signaling Server. Actúa como un “cartero”, entregando invitaciones y configuraciones de conexión entre los participantes de la llamada.
WebSocket — es la opción óptima para la mayoría de las aplicaciones web: full-dúplex, compatible de forma nativa con los navegadores y simple de implementar. Para integración con infraestructura VoIP existente, elija SIP. Para aplicaciones de chat con funciones avanzadas, use XMPP. Para escenarios IoT, use MQTT.
Para escalar un Signaling Server, use escalado horizontal con sincronización a través de Redis Pub/Sub o Kafka. Cada instancia del servidor maneja su parte de las conexiones WebSocket, y se utiliza un bus de datos común para el enrutamiento de mensajes entre servidores. Este enfoque permite manejar millones de sesiones de señalización simultáneas.
El Signaling Server es crítico solo durante la fase de establecimiento de la conexión. Si el servidor deja de estar disponible temporalmente, las llamadas WebRTC activas continúan — el tráfico multimedia fluye directamente entre los pares. El problema surge solo al intentar establecer una nueva conexión. Para mayor confiabilidad, use agrupación de servidores y canales de señalización de respaldo.
Resumen
Desarrollaremos una aplicación móvil llave en mano
IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.
Lea también