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.