Comprensión de INADDR_ANY para la programación de sockets

84

Estoy tratando de programar algunos sockets y, por lo tanto, en el lado del servidor, utilizo htonl(INADDR_ANY). En la medida que entendí, me parece que esta función genera una IP aleatoria (¿estoy en lo cierto?). De hecho, quiero vincular mi enchufe con mi localhost. Pero si ejecuto esto

printf("%d",htonl(INADDR_ANY));

Obtengo 0 como valor de retorno. ¿Alguien podría traer alguna explicación?

épsilones
fuente
9
" ... Yo uso htonl(INADDR_ANY). El documento dice que esta función genera una IP aleatoria ... " Esto no es correcto. ¿Qué documentos te lo dicen?
Alk
1
@alk, de hecho me engaño: estaba leyendo un pdf que pensé que era documentación oficial. Edito mi publicación ahora
epsilones

Respuestas:

132
  1. bind()de INADDR_ANYqué NO "generar una IP aleatoria". Se une a la toma de todas las interfaces disponibles .

  2. Para un servidor, normalmente desea vincularse a todas las interfaces, no solo a "localhost".

  3. Si desea vincular su socket solo a localhost, la sintaxis sería my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1");, luego llame bind(my_socket, (SOCKADDR *) &my_sockaddr, ...).

  4. Da la casualidad de que INADDR_ANYes una constante que resulta ser igual a "cero":

    http://www.castaglia.org/proftpd/doc/devel-guide/src/include/inet.h.html

    # define INADDR_ANY ((unsigned long int) 0x00000000)
    ...
    # define INADDR_NONE    0xffffffff
    ...
    # define INPORT_ANY 0
    ...
    
  5. Si aún no está familiarizado con él, le recomiendo que consulte la Guía de programación de sockets de Beej:

    http://beej.us/guide/bgnet/

Dado que la gente todavía está leyendo esto, una nota adicional:

hombre (7) ip :

Cuando un proceso desea recibir nuevos paquetes o conexiones entrantes, debe vincular un socket a una dirección de interfaz local usando bind (2) .

En este caso, solo un socket IP puede estar vinculado a cualquier par local (dirección, puerto) dado. Cuando se especifica INADDR_ANY en la llamada de vinculación, el socket se vinculará a todas las interfaces locales.

Cuando se llama a listen (2) en un socket no vinculado, el socket se vincula automáticamente a un puerto libre aleatorio con la dirección local establecida en INADDR_ANY.

Cuando se llama a connect (2) en un socket no vinculado, el socket se vincula automáticamente a un puerto libre aleatorio oa un puerto compartido utilizable con la dirección local establecida en INADDR_ANY ...

Hay varias direcciones especiales: INADDR_LOOPBACK (127.0.0.1) siempre se refiere al host local a través del dispositivo de loopback; INADDR_ANY (0.0.0.0) significa cualquier dirección para vincular ...

También:

bind () - Vincula un nombre a un socket :

Si el campo (sin_addr.s_addr) se establece en la constante INADDR_ANY, como se define en netinet / in.h, la persona que llama solicita que el conector esté vinculado a todas las interfaces de red en el host. Posteriormente, los paquetes UDP y las conexiones TCP de todas las interfaces (que coinciden con el nombre vinculado) se enrutan a la aplicación. Esto se vuelve importante cuando un servidor ofrece un servicio a múltiples redes. Al dejar la dirección sin especificar, el servidor puede aceptar todos los paquetes UDP y las solicitudes de conexión TCP realizadas para su puerto, independientemente de la interfaz de red a la que llegaron las solicitudes.

paulsm4
fuente
4
No significa 'enlazar a todas las interfaces'. Si lo hiciera, la salida de netstat sería diferente. Significa 'escuchar en cualquier interfaz'.
Marqués de Lorne
6
Para citar el enlace anterior: "Cuando se especifica INADDR_ANY en la llamada de enlace, el conector se vinculará a todas las interfaces locales". Desde otro enlace: El valor "INADDR_ANY" significa que enlazaremos a cualquiera / todas las direcciones IP que la computadora local tiene actualmente . Pero sí, muchas implementaciones se vincularán a la primera interfaz (no a "todas"). Pero para una PC con una NIC, la diferencia es académica. Con INADDR_ANY, el cliente puede conectarse a cualquiera / todas las IP (por ejemplo, 192.168.1.2 y 127.0.0.1).
paulsm4
5
Lo siento si esta es una pregunta estúpida, pero ¿significa interfaz inalámbrica, ethernet, etc.?
mrQWERTY
3
@ laike9m Te vincularás a 127.0.0.1 cuando quieras poder conectarte al socket solo desde la máquina local. Hay casos de uso para esto cuando el servicio ofrecido por el socket solo está destinado a ser utilizado por otro proceso que es local a la máquina.
dgnuff
2
@ paulsm4 En 3, ¿no puedes usar INADDR_LOOPBACK, en lugar de inet_addr("127.0.0.1")?
John Strood
62

INADDR_ANYse utiliza cuando no es necesario vincular un socket a una IP específica. Cuando usa este valor como la dirección al llamar bind(), el socket acepta conexiones a todas las IP de la máquina.

Barmar
fuente
8

Para unen zócalo con localhost , antes de invocar el aprieto función, sin_addr.s_addr campo de la estructura sockaddr_in debe ajustarse adecuadamente. El valor adecuado puede obtenerse mediante

my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1")

o por

my_sockaddress.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
MichaelGoren
fuente
4

INADDR_ANYindica al socket de escucha que se vincule a todas las interfaces disponibles. Es lo mismo que intentar enlazar inet_addr("0.0.0.0"). Para completar, también mencionaré que también hay IN6ADDR_ANY_INIT para IPv6 y es lo mismo que intentar enlazar a la ::dirección para el socket IPv6.

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

Además, tenga en cuenta que cuando vincula el socket IPv6 a IN6ADDR_ANY_INITsu socket, se vinculará a todas las interfaces IPv6, y también debería poder aceptar conexiones de clientes IPv4 (a través de direcciones asignadas IPv6).

Pavel P
fuente
2

INADDR_ANY es una constante, que contiene 0 en valor. esto se usará solo cuando desee conectarse desde todos los puertos activos que no le interesan ip-add. así que si desea conectar cualquier IP en particular, debe mencionar como my_sockaddress.sin_addr.s_addr = inet_addr ("192.168.78.2")

vivek
fuente