socket example c networking udp broadcast berkeley-sockets

example - Cómo ignorar tus propios paquetes udp de transmisión



udp socket c (5)

Al inicio, podría transmitir un mensaje diferente con un valor aleatorio (pero seguido) y luego esperar ese mensaje para descubrir su propia dirección; a partir de ese momento, puede enviar mensajes normales e ignorar los mensajes originales.

Para lo siguiente, asumo una tarjeta de red.

Tengo un componente de mi programa que está diseñado para permitir que otros en la subred sepan de su existencia. Para esto, he implementado una solución donde cada vez que se inicia el programa (y periódicamente después) envía una transmisión a INADDR_BROADCAST : quien escucha en el puerto requerido recordará de dónde vino para su uso posterior.

El problema con esto es que no quiero recordar mis propias transmisiones. Pensé que, en teoría, esto sería fácil de hacer: simplemente averigua la ip local y compárala con lo que obtienes en recvfrom .

Sin embargo, me ha resultado difícil obtener la IP local: getaddrinfo con NULL devuelve 127.0.0.1 , getaddrinfo con el nombre de host devuelve la IP pública. ¿Alguien puede señalarme en la dirección de encontrar la ip de la subred real? Creo que me estoy perdiendo algo muy obvio aquí, pero bueno ... todavía me lo estoy perdiendo :)

Nota: He leído otras preguntas sobre SO en las transmisiones, en particular esta: UDP-Broadcast en todas las interfaces, pero todavía no me he enterado de la cuestión de la interfaz múltiple.


Busque las opciones de scoket y compruebe si funcionan: IP_MULTICAST_LOOP, IP_BLOCK_SOURCE


En Linux, puede obtener la dirección IP de una interfaz determinada utilizando ioctl con la opción SIOCGIFADDR . Sin embargo, no creo que esto funcione para Windows. Para eso, tendrás que hacer algo tonto como este .


getsockname ( documentación de funciones ) puede descubrir la dirección IP local asociada con un socket en particular. Si llama esto al socket que está utilizando para enviar la transmisión, debería ver la misma dirección IP que verá devuelta desde.


(Supongo que estás trabajando en Windows)

GetIpAddrTable hace exactamente eso! Devuelve datos sobre todas sus interfaces de red, la dirección IP se encuentra entre ellas. Hay algunos engaños en conseguirlos, pero no más que en el resto de Winsocks.

Aquí hay un ejemplo de 54 líneas listo para compilar que imprime todas sus interfaces de red con máscaras de red y de IP, y también filtra su devolución de llamada local (127.0.0.1) ya que lo más probable es que no lo quiera, y siempre está ahí, por lo que no puedes simplemente ignorarlo:

(trabajado con msvc 19, Windows 10, enlace contra Iphlpapi.lib y Ws2_32.lib)

#include "stdio.h" #include "Winsock2.h" #include "Iphlpapi.h" int main(){ int error; ULONG size = 0; MIB_IPADDRTABLE* meta_table = nullptr; error = GetIpAddrTable(meta_table, &size, false); if(error != ERROR_INSUFFICIENT_BUFFER) return -1; meta_table = (MIB_IPADDRTABLE*)malloc(size); error = GetIpAddrTable(meta_table, &size, false); if(error != NO_ERROR) return -1; int os_interface_count = meta_table->dwNumEntries; for(int i = 0; i < os_interface_count; i++){ printf("interface:/n"); { in_addr mask; in_addr address; address.S_un.S_addr = meta_table->table[i].dwAddr; mask.S_un.S_addr = meta_table->table[i].dwMask; printf("index: %d/n", meta_table->table[i].dwIndex); printf("address: %s/n", inet_ntoa(address)); printf("mask: %s/n", inet_ntoa(mask)); } { in_addr callback_address; callback_address.S_un.S_un_b.s_b1 = 127; callback_address.S_un.S_un_b.s_b2 = 0; callback_address.S_un.S_un_b.s_b3 = 0; callback_address.S_un.S_un_b.s_b4 = 1; if(meta_table->table[i].dwAddr == callback_address.S_un.S_addr) printf("local callback!/n"); } } free(meta_table); return 0; }

produciendo esta salida en mi máquina:

interface: index: 7 address: 192.168.56.1 mask: 255.255.255.0 interface: index: 1 address: 127.0.0.1 mask: 255.0.0.0 local callback! interface: index: 11 address: 192.168.178.181 mask: 255.255.255.0

Lo único realmente extraño es la primera llamada a GetIpAddrTable , que simplemente te da el tamaño que necesitas asignar para el buffer. Creo que el resto del código es bastante explicativo, si no, estoy aquí para hacer preguntas. (No tengo 50 Rep, así que no sé si podré responder preguntas, ¡Gracias !)