Grundlegendes zu INADDR_ANY für die Socket-Programmierung

83

Ich versuche einige Sockets zu programmieren und benutze sie daher auf der Serverseite htonl(INADDR_ANY). Soweit ich verstanden habe, scheint mir diese Funktion eine zufällige IP zu generieren (bin ich richtig?). Tatsächlich möchte ich meine Steckdose mit meiner binden localhost. Aber wenn ich das mache

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

Ich bekomme 0 als Rückgabewert. Könnte jemand eine Erklärung bringen?

Epsilone
quelle
9
" ... ich benutze htonl(INADDR_ANY). Das Dokument sagt, dass diese Funktion eine zufällige IP generiert ... " Dies ist nicht korrekt. Welche Dokumente sagen es Ihnen?
Alk
1
@alk, in der Tat irreführend: Ich habe ein PDF gelesen, von dem ich dachte, es sei eine offizielle Dokumentation. Ich bearbeite meinen Beitrag jetzt
epsilones

Antworten:

131
  1. bind()von INADDR_ANYtut NICHT „eine zufällige IP erzeugen“. Es bindet den Socket an alle verfügbaren Schnittstellen .

  2. Bei einem Server möchten Sie normalerweise an alle Schnittstellen binden - nicht nur an "localhost".

  3. Wenn Sie Ihren Socket nur an localhost binden möchten, lautet die Syntax: my_sockaddress.sin_addr.s_addr = inet_addr("127.0.0.1");Rufen Sie dann auf bind(my_socket, (SOCKADDR *) &my_sockaddr, ...).

  4. Zufällig INADDR_ANYist eine Konstante gleich "Null":

    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. Wenn Sie noch nicht damit vertraut sind, empfehlen wir Ihnen, den Beej-Leitfaden zur Sockets-Programmierung zu lesen:

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

Da die Leute dies noch lesen, ein zusätzlicher Hinweis:

Mann (7) ip :

Wenn ein Prozess neue eingehende Pakete oder Verbindungen empfangen möchte, sollte er einen Socket mit bind (2) an eine lokale Schnittstellenadresse binden .

In diesem Fall darf nur ein IP-Socket an ein bestimmtes lokales Paar (Adresse, Port) gebunden sein. Wenn im Bindungsaufruf INADDR_ANY angegeben ist, wird der Socket an alle lokalen Schnittstellen gebunden.

Wenn listen (2) an einem ungebundenen Socket aufgerufen wird, wird der Socket automatisch an einen zufälligen freien Port gebunden, wobei die lokale Adresse auf INADDR_ANY gesetzt ist.

Wenn connect (2) an einem ungebundenen Socket aufgerufen wird, wird der Socket automatisch an einen zufälligen freien Port oder an einen verwendbaren gemeinsam genutzten Port gebunden, wobei die lokale Adresse auf INADDR_ANY gesetzt ist ...

Es gibt mehrere spezielle Adressen: INADDR_LOOPBACK (127.0.0.1) bezieht sich immer über das Loopback-Gerät auf den lokalen Host; INADDR_ANY (0.0.0.0) bedeutet eine beliebige Adresse für die Bindung ...

Ebenfalls:

bind () - Bindet einen Namen an einen Socket :

Wenn das Feld (sin_addr.s_addr) auf die Konstante INADDR_ANY gesetzt ist, wie in netinet / in.h definiert, fordert der Anrufer an, dass der Socket an alle Netzwerkschnittstellen auf dem Host gebunden wird. Anschließend werden UDP-Pakete und TCP-Verbindungen von allen Schnittstellen (die mit dem gebundenen Namen übereinstimmen) an die Anwendung weitergeleitet. Dies ist wichtig, wenn ein Server einen Dienst für mehrere Netzwerke anbietet. Wenn Sie die Adresse nicht angeben, kann der Server alle UDP-Pakete und TCP-Verbindungsanforderungen für seinen Port akzeptieren, unabhängig von der Netzwerkschnittstelle, auf der die Anforderungen eingegangen sind.

paulsm4
quelle
4
Es bedeutet nicht "an alle Schnittstellen binden". Wenn dies der Fall wäre, wäre die Netstat-Ausgabe anders. Es bedeutet "an jeder Schnittstelle abhören ".
Marquis von Lorne
6
Um den obigen Link zu zitieren: "Wenn INADDR_ANY im Bindungsaufruf angegeben ist, wird der Socket an alle lokalen Schnittstellen gebunden." Von einem anderen Link: Der Wert "INADDR_ANY" bedeutet, dass wir an alle IP-Adressen binden, die der lokale Computer derzeit hat . Aber ja - viele Implementierungen werden an die erste Schnittstelle gebunden (nicht "alle"). Bei einem PC mit einer Netzwerkkarte ist der Unterschied jedoch akademisch. Mit INADDR_ANY kann der Client eine Verbindung zu einer beliebigen IP-Adresse herstellen (z. B. 192.168.1.2 und 127.0.0.1).
Pauls4
5
Entschuldigung, wenn dies eine dumme Frage ist, aber bedeutet Schnittstelle drahtlos, Ethernet usw.?
mrQWERTY
3
@ laike9m Sie würden an 127.0.0.1 binden, wenn Sie nur vom lokalen Computer aus eine Verbindung zum Socket herstellen möchten. Es gibt Anwendungsfälle hierfür, in denen der vom Socket angebotene Dienst nur von einem anderen Prozess verwendet werden soll, der lokal für die Maschine ist.
Dgnuff
2
@ paulsm4 Kannst du in 3 nicht INADDR_LOOPBACKstatt inet_addr("127.0.0.1")?
John Strood
61

INADDR_ANYwird verwendet, wenn Sie keinen Socket an eine bestimmte IP binden müssen. Wenn Sie diesen Wert beim Anrufen als Adresse verwenden bind(), akzeptiert der Socket Verbindungen zu allen IP- Adressen des Computers.

Barmar
quelle
7

Um binden Buchse mit localhost , bevor Sie rufen Sie die bind Funktion sollte sin_addr.s_addr Feld der sockaddr_in Struktur richtig eingestellt werden. Der richtige Wert kann entweder durch erhalten werden

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

oder von

my_sockaddress.sin_addr.s_addr=htonl(INADDR_LOOPBACK);
MichaelGoren
quelle
3

INADDR_ANYWeist den Listening-Socket an, sich an alle verfügbaren Schnittstellen zu binden. Es ist das gleiche wie der Versuch, sich zu binden inet_addr("0.0.0.0"). Der Vollständigkeit halber werde ich auch erwähnen, dass es auch IN6ADDR_ANY_INIT für IPv6 gibt und es das gleiche ist wie der Versuch, an die ::Adresse für den IPv6-Socket zu binden .

#include <netinet/in.h>

struct in6_addr addr = IN6ADDR_ANY_INIT;

Beachten Sie außerdem, dass beim Binden des IPv6-Sockets an IN6ADDR_ANY_INITIhren Socket alle IPv6-Schnittstellen gebunden werden und auch Verbindungen von IPv4-Clients akzeptiert werden sollten (obwohl IPv6-zugeordnete Adressen).

Pavel P.
quelle
1

INADDR_ANY ist eine Konstante, deren Wert 0 enthält. Dies wird nur verwendet, wenn Sie eine Verbindung von allen aktiven Ports herstellen möchten, für die Sie sich nicht für IP-Add interessieren. Wenn Sie also eine bestimmte IP-Adresse verbinden möchten, sollten Sie Folgendes als my_sockaddress.sin_addr.s_addr = inet_addr ("192.168.78.2") angeben.

vivek
quelle