socket servidor por enviar ejemplos cliente archivos c++ sockets udp

c++ - servidor - sockets unix



Cómo obtener su propia dirección IP(local) desde un socket udp(C/C++) (6)

Gday,

Supongo que ha realizado el enlace usando INADDR_ANY para especificar la dirección.

Si este es el caso, entonces la semántica de INADDR_ANY es tal que se crea un socket UDP en el puerto especificado en todas sus interfaces. El socket va a enviar todos los paquetes a todas las interfaces en el puerto especificado.

Al enviar utilizando este conector, se utiliza la interfaz con el número más bajo. El campo de dirección del remitente saliente se establece en la dirección IP de la primera interfaz de salida utilizada.

La primera interfaz de salida se define como la secuencia cuando haces un ifconfig -a. Probablemente será eth0.

HTH.

aplausos, Rob

  1. Tienes múltiples adaptadores de red.
  2. Enlace un socket UDP a un puerto local, sin especificar una dirección.
  3. Reciba paquetes en uno de los adaptadores.

¿Cómo se obtiene la dirección IP local del adaptador que recibió el paquete?

La pregunta es: "¿Cuál es la dirección IP del adaptador del receptor?" no la dirección del remitente que obtenemos en el

receive_from( ..., &senderAddr, ... );

llamada.


Puede enumerar todos los adaptadores de red, obtener sus direcciones IP y comparar la parte cubierta por la máscara de subred con la dirección del remitente.

Me gusta:

IPAddress FindLocalIPAddressOfIncomingPacket( senderAddr ) { foreach( adapter in EnumAllNetworkAdapters() ) { adapterSubnet = adapter.subnetmask & adapter.ipaddress; senderSubnet = adapter.subnetmask & senderAddr; if( adapterSubnet == senderSubnet ) { return adapter.ipaddress; } } }


ssize_t recvfrom(int socket, void *restrict buffer, size_t length, int flags, struct sockaddr *restrict address, socklen_t *restrict address_len); ssize_t recvmsg(int socket, struct msghdr *message, int flags); [..] If address is not a null pointer and the socket is not connection-oriented, the source address of the message is filled in.

Código actual:

int nbytes = recvfrom(sock, buf, MAXBUFSIZE, MSG_WAITALL, (struct sockaddr *)&bindaddr, &addrlen);

fprintf (stdout, "Leer% d bytes en la dirección local% s / n", nbytes, inet_ntoa (bindaddr.sin_addr.s_addr));

espero que esto ayude.


Prueba esto:

gethostbyname("localhost");


La solución provista por timbo supone que los rangos de direcciones son únicos y no se superponen. Si bien este suele ser el caso, no es una solución genérica.

Hay una excelente implementación de una función que hace exactamente lo que está buscando, provisto en el libro de Steven "Programación de red Unix" (sección 20.2) Esta es una función basada en recvmsg (), en lugar de recvfrom (). Si su socket tiene habilitada la opción IP_RECVIF, entonces recvmsg () devolverá el índice de la interfaz en la que se recibió el paquete. Esto se puede usar para buscar la dirección de destino.

El código fuente está disponible aquí . La función en cuestión es ''recvfrom_flags ()''


Lamentablemente, las llamadas a la API de envío y recepción se rompen fundamentalmente cuando se utilizan con sockets vinculados a "Cualquier IP" porque no tienen campo para la información de IP local.

Entonces, ¿qué puede hacer usted al respecto?

  1. Puede adivinar (por ejemplo, basado en la tabla de enrutamiento).
  2. Puede obtener una lista de direcciones locales y vincular un socket separado a cada dirección local.
  3. Puede usar API más nuevas que admitan esta información. Hay dos partes para esto, en primer lugar debe usar la opción relavent socket (ip_recvif para IPv4, ipv6_recvif para IPv6) para indicarle a la pila que desea esta información. Luego debe usar una función diferente (recvmsg en Linux y varios otros sistemas unix, WSArecvmsg en Windows) para recibir el paquete.

Ninguna de estas opciones es genial. Adivinar obviamente producirá respuestas equivocadas a la vez. La vinculación de sockets separados aumenta la complejidad de su software y causa problemas si la lista de direcciones locales cambia su programa se está ejecutando. Las API más nuevas son la solución técnica correcta, pero pueden reducir la portabilidad (en particular, parece que WSArecvmsg no está disponible en Windows XP) y pueden requerir modificaciones en la biblioteca de contenedor que está utilizando.

Editar parece que estaba equivocado, parece que la documentación de MS es engañosa y que WSArecvmsg está disponible en Windows XP. Ver https://.com/a/37334943/5083516