web-dev-qa-db-fra.com

Comprendre INADDR_ANY pour la programmation de sockets

J'essaie de programmer des sockets et donc, côté serveur, j'utilise htonl(INADDR_ANY). Dans la mesure où j'ai compris, il me semble que cette fonction génère une adresse IP aléatoire (est-ce que j'ai raison?). En fait, je veux lier mon socket avec mon localhost. Mais si je lance ça

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

Je reçois 0 comme valeur de retour. Quelqu'un pourrait-il apporter une explication?

70
epsilones
  1. bind() sur INADDR_ANY ne PAS "génère une adresse IP aléatoire". It lie le socket à toutes les interfaces disponibles .

  2. Pour un serveur, vous souhaitez généralement établir une liaison avec toutes les interfaces - pas seulement "localhost".

  3. Si vous souhaitez lier votre socket à localhost uniquement, la syntaxe serait my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1");, puis appelez bind(my_socket, (SOCKADDR *) &my_sockaddr, ...).

  4. Il se trouve que INADDR_ANY est une constante égale à "zéro":

    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 vous ne le connaissez pas déjà, je vous invite à consulter le Guide de Beej sur la programmation de sockets:

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

Puisque les gens lisent encore ceci, une note supplémentaire:

man (7) ip :

Lorsqu'un processus souhaite recevoir de nouveaux paquets ou connexions entrants, il doit lier une socket à une adresse d'interface locale à l'aide de bind (2) .

Dans ce cas, un seul socket IP peut être lié à une paire locale donnée (adresse, port). Lorsque INADDR_ANY est spécifié dans l'appel de liaison, le socket sera lié à toutes les interfaces locales.

Lorsque listen (2) est appelé sur une socket non liée, la socket est automatiquement liée à un port libre aléatoire avec l'adresse locale définie sur INADDR_ANY.

Lorsque connect (2) est appelé sur une socket non liée, la socket est automatiquement liée à un port libre aléatoire ou à un port partagé utilisable avec l'adresse locale définie sur INADDR_ANY ...

Il existe plusieurs adresses spéciales: INADDR_LOOPBACK (127.0.0.1) fait toujours référence à l'hôte local via le périphérique de bouclage; INADDR_ANY (0.0.0.0) désigne toute adresse permettant de lier ...

Aussi:

bind () - Lie un nom à une socket :

Si le champ (sin_addr.s_addr) est défini sur la constante INADDR_ANY, telle que définie dans netinet/in.h, l'appelant demande que le socket soit lié à toutes les interfaces réseau de l'hôte. Ensuite, les paquets UDP et les connexions TCP de toutes les interfaces (qui correspondent au nom lié) sont routés vers l'application. Cela devient important lorsqu'un serveur offre un service à plusieurs réseaux. En laissant l'adresse non spécifiée, le serveur peut accepter tous les paquets UDP et les demandes de connexion TCP effectuées pour son port, quelle que soit l'interface réseau sur laquelle les demandes sont arrivées.

100
paulsm4

INADDR_ANY est utilisé lorsque vous n'avez pas besoin de lier un socket à une adresse IP spécifique. Lorsque vous utilisez cette valeur comme adresse lorsque vous appelez bind(), le socket accepte les connexions à toutes les adresses IP de la machine.

57
Barmar

Pour bind socket avec localhost, avant d'appeler la fonction bind, le champ sin_addr.s_addr de la structure sockaddr_in doit être défini correctement. La valeur appropriée peut être obtenue soit par

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

ou par

my_sockaddress.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
7
MichaelGoren

INADDR_ANY indique au socket en écoute de se lier à toutes les interfaces disponibles. C'est la même chose que d'essayer de se lier à inet_addr("0.0.0.0"). Pour être complet, je mentionnerai également qu’il existe également IN6ADDR_ANY_INIT pour IPv6 et que cela revient à essayer de se lier à :: adresse pour socket IPv6.

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

Notez également que lorsque vous liez le socket IPv6 à IN6ADDR_ANY_INIT, votre socket se liera à toutes les interfaces IPv6 et devrait également pouvoir accepter les connexions des clients IPv4 (bien que les adresses mappées IPv6).

1
Pavel

INADDR_ANY est une constante qui contient 0 en valeur. cela ne sera utilisé que lorsque vous voulez vous connecter à partir de tous les ports actifs dont vous ne vous souciez pas de ip-add. Donc, si vous voulez connecter une adresse IP particulière, vous devez la mentionner comme mon adresse_sockaddress.sin_addr.s_addr = inet_addr ("192.168.78.2")

1
vivek