Las redes de área local (LAN) que usan tecnologías como Ethernet y Wi-Fi son increíblemente útiles para que los dispositivos se comuniquen entre sí. El problema, sin embargo, es saber qué dispositivo está dónde en la red. Cualquiera que haya intentado agregar una impresora de red o un share SMB al sistema ya lo probó en carne propia. A menos que se sepa la IP del dispositivo LAN, el puerto y el protocolo, el dispositivo destino termina siendo tan alcanzable como si estuviera en la Luna, salvo que exista auto-discovery de red.
Durante las últimas décadas se desarrollaron varias formas de habilitar este descubrimiento, y muchas usan UDP broadcast como primer paso. Al enviar un mensaje global a toda la LAN, cualquier dispositivo con un socket UDP escuchando en ese puerto puede parsear el mensaje y decidir si "está de humor" para responder.
El tema no es tan lineal como suena. Hay tantas opiniones sobre "la forma correcta" como personas involucradas. Además existe una división enorme entre un protocolo pesado como mDNS y una alternativa liviana como la que el autor tuvo que implementar hace algunos años para un proyecto open source.
¿Cómo funciona un broadcast en la red?
La ventaja obvia del mensaje broadcast es que el cliente que busca a otro dispositivo con el mismo protocolo no necesita hacer ping a todas las IP posibles y a todas las subredes. En cambio, el mensaje broadcast está diseñado para que todos los dispositivos de la red sepan que debe ser reenviado a todos los demás. Con un solo mensaje del cliente, en teoría, una única copia llega a cada otro sistema conectado.
Esto ignora complicaciones como configuraciones enredadas de red, por ejemplo repetidores Wi-Fi solapados y ruteo entre ellos, pero en general así funciona.

Buena parte del auto-discovery se agrupa bajo la etiqueta zero-configuration networking, o zeroconf para los que evitan tipear. Lo mejor de zeroconf es probablemente que existen muchos estándares: DNS-SD, mDNS, UPnP, SLP y otros. Sin sorpresas, el mayor problema es que el soporte de plataforma es parche: mDNS, uno de los más universales, no tiene mucho soporte fuera de macOS/OS X vía Bonjour y Linux/BSD vía Avahi.
¿Qué es NyanSD y por qué implementarlo?
Al querer agregar auto-discovery de receptores y servidores de medios de NymphCast, el autor se encontró preguntándose si estaba a punto de reinventar la rueda. Pero después de buscar en todas partes no encontró nada parecido al protocolo de network service discovery (NSD) NyanSD (overview y requerimientos) que terminó implementando e integrando en NymphCast. Quería el NSD más simple posible, fácil de integrar y que corriera igual en cualquier plataforma desktop, servidor y embebida imaginable.
Todo lo necesario es crear un socket UDP apropiado y tener una forma de emitir un query en broadcast, recibir la respuesta, o escuchar paquetes UDP entrantes. Aquí se puede resolver con la API nativa de cada plataforma o usar una librería de networking existente para C++ como Poco. Ese fue el camino elegido para NyanSD, junto con la utilidad ByteBauble del autor para manejar conversiones de endianness.
Cliente y servidor del broadcast
Para el servidor UDP, el lado que escucha, el procedimiento es bastante estándar con un socket UDP normal. Como UDP es un protocolo sin conexión, no hay mucho preámbulo: solo una instancia de socket (aquí Poco::Net::DatagramSocket), asociada al puerto destino, que hace polling regular de paquetes UDP nuevos para procesar. Todo esto se ve en el único archivo fuente de NyanSD que cubre tanto la parte cliente como la servidor.
Donde la cosa se pone picante es en el cliente que emite el query broadcast y espera respuestas. Si simplemente se metieran los datos de la query en el socket y se pidiera enviarlos a una IP normal, no pasaría gran cosa. Para convertir la solicitud en broadcast se necesita:
- Avisar al subsistema de red que uno quiere hacer broadcast).
- Crear la dirección broadcast especial para la interfaz de red destino.
Con Poco, el primer punto se resuelve simplemente llamando setBroadcast(true) sobre la instancia del socket UDP. En BSD sockets esto setea el flag apropiado en el socket, cosa que se repite en casi todas las implementaciones OS debido a lo generalizado que está la librería BSD sockets.
El segundo punto, en IPv4, se resume en "hacé que termine en .255". Por ejemplo, 192.168.0.255 cuando la IP de la interfaz de red del cliente es 192.168.0.42. Si hay múltiples interfaces en el sistema cliente, se puede recorrer la lista una por una y emitir broadcast en cada una antes de filtrar duplicados potenciales.
En cuanto a hacer broadcast en IPv6: no se puede. Ese protocolo depende de multicast y grupos receptores multicast especiales, otro tema completamente distinto y no muy relevante para LAN.
Complicaciones al implementarlo
Al ver la API de NyanSD, la impresión es que el proceso del query es directísimo: la función sendQuery() devuelve limpio un stack de sistemas remotos que respondieron. Aunque efectivamente devuelve todas las respuestas, es importante recordar que NyanSD consulta todas y cada una de las interfaces de red. Eso significa que las respuestas suelen contener duplicados, incluso desde la dirección de loopback cuando el servicio corre localmente.
El filtrado se resuelve en la librería cliente NymphCast (libnymphcast), donde la función findServers() en el archivo fuente principal llama a isDuplicate(), isDuplicateName() y removeLoopback(), que descarta cualquier respuesta que coincida con un servicio remoto ya hallado vía una interfaz no-loopback. Este último filtrado es esencial para NymphCast cuando se usan playback groups, que si no se confunden con una dirección loopback perdida.
Aunque parezca que ese nivel de filtrado es innecesario si solo hay una interfaz Wi-Fi o Ethernet, uno de los curveballs que apareció en pruebas reales tuvo que ver con repetidores Wi-Fi. Por algún motivo, la forma en que los repetidores hacían broadcast llevaba a duplicación errónea de paquetes y por lo tanto múltiples respuestas del mismo sistema.
¿Por qué NyanSD funcionó?
A lo largo de los años que NyanSD lleva siendo usado en NymphCast, ha sido uno de los componentes más confiables y con menos fricción. Se ha usado en Windows, distintas distribuciones Linux, FreeBSD, Haiku, Android y en ESP32 vía FreeRTOS y ESP-IDF. La experiencia demuestra que el service discovery no tiene por qué ser complicado.
El protocolo UDP básico es simple y confiable, y salvo una LAN muy enferma, no debería haber problemas. Asumiendo que el filtrado de respuestas está resuelto, probablemente sea la última parte del proyecto por la que preocuparse.
Un aspecto que el autor destaca de NyanSD es que no tiene un puerto fijo en el protocolo, a diferencia de mDNS, que siempre usa el puerto 5353. Eso permite que NyanSD escuche con un socket UDP en el mismo puerto que el socket TCP del servidor NymphCast. También significa que servicios distintos con su propio puerto pueden ser interrogados directamente, en vez de que cada consulta NyanSD termine bombardeando a todos los servicios habilitados de la red.
El autor también trabajó en un daemon NyanSD como una base de datos centralizada de servicios, pero hasta ahora no ha sentido necesidad real en un despliegue en producción. Podría ser útil si el puerto del servicio no es fijo, aunque en general ese aspecto de los servicios de red suele ser aburridamente predecible.




