121 votes

Comprendre INADDR_ANY pour la programmation de socket

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

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

J'obtiens 0 comme valeur de retour. Quelqu'un pourrait-il m'expliquer ?

195voto

paulsm4 Points 39422
  1. bind() de INADDR_ANY fait PAS "générer une IP aléatoire". C'est lie la socket à toutes les interfaces disponibles .

  2. Pour un serveur, vous souhaitez généralement vous lier à toutes les interfaces, et pas seulement à "localhost".

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

  4. Il se trouve que, INADDR_ANY est une constante qui se trouve être é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 n'êtes pas déjà familiarisé avec cette technologie, je vous invite à consulter le guide de Beej sur la programmation des sockets :

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

Puisque des gens lisent encore ce texte, une note supplémentaire :

homme (7) ip :

Lorsqu'un processus veut recevoir de nouveaux paquets ou connexions entrants, il doit lier une socket à une adresse d'interface locale en utilisant lier(2) .

Dans ce cas, une seule socket IP peut être liée à un local donné. (adresse, port) donnée. Lorsque INADDR_ANY est spécifié dans l'appel bind, la socket sera liée à toutes les interfaces locales.

Lorsque écouter(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 comme à INADDR_ANY.

Lorsque connecter(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 comme 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) signifie n'importe quelle adresse pour la liaison...

Aussi :

bind() - Relie un nom à un fichier socket :

Si le champ (sin_addr.s_addr) est défini comme la constante INADDR_ANY, telle que définie dans netinet/in.h, l'appelant demande que la socket soit liée à toutes les liée à toutes les interfaces réseau de l'hôte. Par la suite, les paquets UDP et les connexions TCP de toutes les interfaces (qui correspondent au nom lié) sont acheminé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 connexions TCP. TCP sur son port, quelle que soit l'interface réseau sur laquelle les requêtes sur laquelle les demandes sont arrivées.

74voto

Barmar Points 135986

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

15voto

MichaelGoren Points 842

A lier avec localhost avant d'invoquer l'option lier 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);

10voto

Pavel Points 1715

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 c'est la même chose que d'essayer de se lier à :: adresse pour le socket IPv6.

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

De plus, notez que lorsque vous liez une socket IPv6 à IN6ADDR_ANY_INIT votre socket se liera à toutes les interfaces IPv6, et devrait être capable d'accepter des connexions de clients IPv4 également (avec des adresses mappées en IPv6).

7voto

Lewis Kelsey Points 181

Lorsque vous avez un serveur, vous créez un socket, puis vous le liez à une IP et à un port, ce qui donne au socket un moyen unique d'être identifié sur la base d'un type de socket unique, d'une famille d'adresses, d'une IP et d'un port. Vous utilisez ensuite listen() pour mettre le socket en mode serveur, puis vous faites accept(), qui attend une connexion avec des paquets entrants avec l'IP/le port cible, ce qui fait que les paquets sont mis en file d'attente sur ce socket. Vous n'avez pas besoin de le lier à une IP, cependant, il peut accepter des connexions sur toutes les interfaces.

Lorsque vous avez un client, vous créez un socket, puis vous connectez() le socket à une IP et un port distants, ce qui liera également 0.0.0.0 et un port éphémère aléatoire inutilisé au socket s'il n'a pas déjà été lié à une IP et un port en utilisant bind(INADDR_ANY, 0). connect() revient lorsqu'il se connecte, et utilise l'IP et le port comme adresse source dans les paquets sortants, où 0.0.0.0 est toujours remplacé par une IP basée sur src hint dans la table de routage ou l'IP de l'interface sélectionnée (si elle a plusieurs IPs, alors la première IP avec la même ou une plus grande portée est sélectionnée), et ensuite vous utilisez sendall pour envoyer les données de l'application.

INADDR_ANY est plus rapide que l'acquisition programmatique de l'IP interne actuelle de l'interface, qui pourrait changer à tout moment, et les paquets ne seront plus reçus sur le port, mais ils seront toujours reçus sur 0.0.0.0 parce que c'est une adresse quelconque.

Notez qu'une socket peut être liée à 0.0.0.0, mais pas au port 0, parce que c'est un joker qui donne à la socket un port éphémère aléatoire, donc lorsque vous utilisez bind(INADDR_ANY, 0), il se lie à 0.0.0.0 et à un port éphémère aléatoire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X