Recién implementaste un chat en WebRTC y te confunden los ICE Candidates. No eres el único. Entender de dónde vienen y cómo se usan es clave para depurar tus conexiones peer-to-peer. Es una de esas piezas de la infraestructura de red que, aunque no siempre vemos, son fundamentales.
¿Qué son los ICE Candidates y por qué son necesarios?
ICE significa Interactive Connectivity Establishment. En la práctica, es un conjunto de técnicas para establecer comunicación en escenarios complejos, como VoIP o conexiones peer-to-peer, especialmente cuando hay NATs (Network Address Translators) y firewalls de por medio. Piensa en ellos como un listado de posibles rutas o puntos de acceso a tu máquina en la red.
Cada ICE Candidate es una dirección IP y un puerto por donde tu aplicación podría ser alcanzada. Cuando tu navegador genera estos candidatos, está haciendo un escaneo de todas las interfaces de red que tiene tu computador y las rutas disponibles para llegar a él. De hecho, si tienes varias tarjetas de red, interfaces virtuales (como las de Hyper-V o Docker), o estás detrás de múltiples routers, cada una de esas "puertas" generará uno o más candidatos.
El formato de un candidato se ve más o menos así en la descripción SDP:
a=candidate:1 1 UDP 2130706431 192.168.1.102 1816 typ host
UDP: Es el protocolo de transporte.192.168.1.102: La dirección IP.1816: El puerto.typ host: Indica el tipo de candidato. Unhostcandidate se genera directamente en tu máquina. También existen candidatossrflx(Server Reflexive) obtenidos de un servidor STUN, yrelay, que provienen de un servidor TURN, útiles cuando la conexión directa no es posible.
Que tu colega obtenga menos candidatos se debe justo a eso: la cantidad y complejidad de sus interfaces de red. Si tiene menos adaptadores, menos VPNs activas o una configuración de red más simple, generará menos opciones de conexión.
El intercambio y la elección de candidatos
Una vez que tu aplicación tiene su lista de candidatos, los intercambia con el otro peer (a través de un signaling server, que es otro tema). Cada peer recibe la lista del otro y entonces comienza el proceso de "chequeo de conectividad". Básicamente, intentan conectarse usando todas las combinaciones posibles de sus candidatos.
El objetivo es encontrar la ruta más corta y eficiente. Si ambos están en la misma red local, lo más probable es que se conecten directamente a través de un candidato host. Si hay NATs de por medio, los candidatos srflx (STUN) entran en juego. Y en el peor de los casos, si ninguna conexión directa o semi-directa es posible, se recurrirá a un candidato relay a través de un servidor TURN, que básicamente retransmite el tráfico.
El proceso es bastante inteligente y busca la mejor opción por sí mismo. Para mí, ojo que, es una de las magias de WebRTC: gran parte de esta complejidad de red se abstrae.
Mi opinión y recomendación
Entender los ICE Candidates es importante, sobre todo cuando las cosas fallan. A veces me frustra la cantidad de capas de abstracción que hay, pero al final del día, WebRTC nos soluciona un problema gigantesco que de otra forma sería un infierno de implementar. No siempre necesitas saber cada detalle de la negociación de puertos, pero sí comprender el concepto de "rutas posibles".
Mi recomendación es que, a menos que estés teniendo problemas de conectividad persistentes o necesites optimizar algo muy específico, confíes en que el stack de WebRTC y el navegador harán bien su trabajo. Concéntrate en la lógica de tu aplicación y en un buen signaling server. Si las conexiones no se establecen, entonces sí, es momento de bucear más profundo en tus ICE Candidates y en los logs de tu navegador para ver qué rutas se están intentando y cuáles fallan.