Frage

Für eine Kommunikation zwischen zwei Rechnern, muss ich die IP-Adresse meines Gastgebers auf der anderen Seite senden. Das Problem ist, dass, wenn ich meine IP-Adresse anfordern, könnte es sein, dass ich mein lokales Loopback-IP addres (127.x.x.x) zurück, nicht das Netzwerk (Ethernet) IP-Adresse.

Ich verwende den folgenden Code:

char myhostname[32];


gethostname(myhostname, 32);
hp = gethostbyname(myhostname);
unsigned my_ip = *(unsigned*)(hp->h_addr);

if( (my_ip % 256) == 127) {
  /* Wrong IP adress as it's 127.x.x.x */
  printf("Error, local IP address!");
  return;
}

Der einzige Weg, um es zu lösen ist mein Hostname in / etc / hosts, um sicherzustellen, hinter der realen Netzwerk-Adresse, nicht der lokale Loopback (Standardeinstellung für beispielsweise Ubuntu).

Gibt es eine Möglichkeit, dies zu lösen, ohne etc auf den Inhalt von / Berufung / hosts?

Edit: änderte ich den obigen Code, so dass es die Verwendung von getaddrinfo macht, aber ich habe immer noch die Loopback-Device Nummer (127.0,0,1) anstelle der realen IP-Adresse zurück:

struct addrinfo hint = {0};
struct addrinfo *aip = NULL;
unsigned ip = 0;
struct sockaddr_in *sinp = NULL;

hint.ai_family = AF_INET; /* IPv4 */
hint.ai_socktype = SOCK_STREAM;

if(getaddrinfo(hostname, NULL, &hint, &aip) != 0) {
    return 0;
}
sinp = (struct sockaddr_in *) aip->ai_addr;
ip   = *(unsigned *) &sinp->sin_addr;

(Ich habe mit der drei eine Liste von 3 addrinfo ist, um wieder SOCK_STREAM, SOCK_DGRAM und SOCK_RAW, aber der Hinweis, dass verhindert)

Also meine Frage steht immer noch ...

War es hilfreich?

Lösung

Es ist POSIX-Funktion getaddrinfo(), die Liste der Adressen für bestimmte Hostnamen verknüpft Returns, so brauchen Sie nur durch diese Liste zu gehen und nicht-Loopback-Adresse finden.

Siehe man getaddrinfo.

Andere Tipps

Nicht eine Antwort, aber ein relevantes Kommentar: bewusst sein, dass, sobald Sie starten das Senden von Informationen in dem Inhalt von Paketen Adressierung, können Sie die Gefahr, dass die Anwendung nicht in der Lage führen a href = "http arbeitet über <: // sv.wikipedia.org/wiki/Network_Address_Translation“rel = "nofollow noreferrer"> NAT: ing. Router und / oder durch Firewalls

Diese Technologien stützen sich auf den Informationen, die in IP-Paket-Header Spur des Verkehrs zu halten, und wenn Anwendungen zum Austausch von Informationen innerhalb Pakete adressiert, wo sie zu dieser Inspektion unsichtbar bleiben, könnten sie brechen.

Natürlich könnte dies zu Ihrer Anwendung völlig irrelevant sein, aber ich dachte, dass es in diesem Zusammenhang darauf hinzuweisen.

Die Ursprungsadresse wird in das Paket aufgenommen werden gesendet ... es gibt keine Notwendigkeit, diese Informationen zu duplizieren. Es wird erhalten, wenn die Kommunikation von dem entfernten Host zu akzeptieren (siehe beej Leitfaden für die Vernetzung, insbesondere den Teil auf accept () )

Ich lief in eine Situation, in der, wenn nur / etc / hosts Informationen in ihm hat, und wenn ich Getaddrinfo verwendet, um die IP-Adressliste zu bekommen, es wieder jedes Mal 127.0.0.1. Wie sich herausstellte, wurde der Hostname aliased auf localhost ... etwas oft leicht zu übersehen. Hier ist, was passiert ist:

Die Datei / etc / hosts-Datei:
127.0.0.1 localhost localhost.localdomain foo
:: 1 localhost6.localdomain6 localhost6
172.16.1.248 foo
172.16.1.249 bie
172.16.1.250 bletch

So, jetzt, wenn Sie rufen mit host = "foo" Getaddrinfo, es gibt 127.0.0.1 3 mal. Der Fehler hier ist, dass foo sowohl mit „127.0.0.1“ auf der Linie erscheint und „172.16.1.248“. Sobald ich foo aus der Zeile mit „127.0.0.1“ Dingen entfernt hat gut funktioniert.

Hoffe, das hilft jemand.

Blick auf diese: Discovering öffentliche IP-programmatisch

Beachten Sie, dass ein Computer in einigen Fällen mehr als eine Adresse Nicht-Loopback-IP haben kann, und in diesem Fall ist die Antworten auf diese Frage Ihnen sagen, wie die eine, die mit dem Internet ausgesetzt ist.

Auch wenn der Rechner nur eine physikalische Netzwerkschnittstelle hat (eine Annahme, die nicht halten kann oder nicht, sogar Netbooks haben zwei - Ethernet und WLAN), VPNs noch mehr IP-Adressen hinzufügen. Wie auch immer, der Host auf der anderen Seite sollte die IP-Host-feststellen kann, verwendeten sie kontaktieren.

Verwenden Sie getaddrinfo()

Sie haben es fast geschafft. Ich bin mir nicht sicher, wie Sie my_ip von hp sind immer.

gethostbyname() gibt einen Zeiger auf eine Struktur, die eine hostent h_addr_list Feld hat.

Das h_addr_list Feld ist eine Null-terminierte Liste aller IP-Adressen an diesen Host gebunden.

Ich denke, Sie bekommen die Loopback-Adresse, weil es der erste Eintrag in h_addr_list ist.

EDIT: Es sollte wie folgt funktionieren:

gethostname(myhostname, 32);
hp = gethostbyname(myhostname);
unsigned my_ip = *(unsigned*)(hp->h_addr);

for (int i = 0; hp->h_addr_list[i] != 0; ++i) {
  if (hp->h_addr_list[i] != INADDR_LOOPBACK) {
    // hp->addr_list[i] is a non-loopback address
  }
}
// no address found

Wenn / etc / hosts ist immer noch da und immer noch die gleiche, für alle Einträge von h_addr_list sucht, wird nicht helfen.

Ihr neuer Code hardwires die Verwendung von IPv4 (im hint.ai_family Feld), die eine schreckliche Idee ist.

Abgesehen davon, dass Sie sind in der Nähe, sollten Sie nur eine Schleife durch die Ergebnisse von getaddrinfo. Ihr Code wird nur die erste IP-Adresse, aber es ist eine aip-> ai_next Feld zu folgen ...

struct addrinfo {
       ...
       struct addrinfo *ai_next;       /* next structure in linked list */
};
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top