2015-02-07 9 views
6

Ich schreibe ein Programm, das mit verschiedenen Websites verbinden und Webseiten anfordern und herunterladen würde. Ich mache das zu einem großen Teil, um Web-Programmierung zu lernen und richtig zu verstehen. Ich würde gerne wissen, ob der Zeiger auf eine verkettete Liste des Typs zurückgegeben von getaddrinfo in einer bestimmten Reihenfolge angeordnet ist, und wenn ja, die IP-Adresse gewählt, um in irgendeiner Weise zu verbinden. Wenn ich beispielsweise getaddrinfo("google.com", "http", &hints, &res) starte, wird res manchmal bis zu sieben Internetadressen haben. Macht es irgendeinen Unterschied, wenn ich mich mit dem ersten oder dem letzten verbinde? Bitte beachten Sie, dass ich die Manpages für diese Funktion gelesen habe und meine Frage dort nicht beantwortet wird.Welche addrinfo-Struktur sollte in connect() verwendet werden?

+0

Ich würde vermuten, dass die Reihenfolge der DNS-Eintrag für die Domäne entspricht, die Sie nachgeschlagen haben. Vergessen Sie nicht, freeaddrinfo() aufzurufen, wenn Sie mit dem Ergebnis fertig sind. – Yetti99

+0

Danke, ich glaube, dass du teilweise auch eine andere Frage beantwortet hast, die ich untersuchen würde, wenn ich weiter komme. (Wenn Sie neugierig sind, ist es wie getaddrinfo diese Informationen bekommen?, ich plane, eine Quelle für libc zu lesen, nachdem ich fertig bin, es zu lernen). – FutureSci

+1

getaddrinfo führt eine DNS-Abfrage durch. Sie können darüber auf Wikipedia lesen. Wenn Sie eine Linux-Befehlszeile haben, können Sie die Befehle dig oder nslookup ausführen - sie könnten getaddrinfo verwenden, tun dies aber wahrscheinlich direkt, da sie alle Informationen bereitstellen. Hier ist eine Website, die Ihnen Zugriff geben - http://network-tools.com/nslook/ – Yetti99

Antwort

3

Da Sie in einer verknüpften Liste organisiert mehrere addrinfo Strukturen haben, Sie sollten Iterierte über sie und versuchen zu connect, bis eine Verbindung erfolgreich ist. Das heißt:

struct addrinfo *ptr = res; 

while (res != NULL) { 
    int rc = connect(socket_fd, (sockaddr *) ptr->ai_addr, ptr->addr_len); 
    if (rc == 0) 
     break; // we managed to connect successfully 
    // handle error 

Dies ist erforderlich, da der DNS-Lookup mehrere Einträge zurückgeben kann, wodurch die Notwendigkeit einer verketteten Liste haben, um Ihnen zu erlauben, auf sie zuzugreifen. Wenn connect erfolgreich ist, sind Sie fertig; Wenn dies fehlschlägt, sollten Sie versuchen, für jede verfügbare IP-Adresse die Suche zurückzugeben und den Zeiger auf das nächste Element zu setzen. Beachten Sie außerdem, dass connect aus mehreren Gründen fehlschlagen kann. Daher müssen Sie errno auf Fehler überprüfen, die weitere Versuche ermöglichen könnten. Wie @R .. wies darauf hin, müssen Sie auch connect einen neuen Socket übergeben, da sich die Adressfamilie ändern kann, wobei die vorherige freigegeben wird; getaddrinfo wird Ihnen helfen, da diese Informationen im addrinfo Knoten (ai_family) bereitgestellt werden.

Dies ist jedoch in der Regel unnötig: das erste Ergebnis wird in der Regel funktionieren. Persönlich, wenn ich darf, habe ich noch nie die Notwendigkeit gefunden, die verknüpfte Liste zu durchlaufen, aber es ist immer noch gut zu wissen, falls Sie das brauchen könnten.

getaddrinfo(3)

Es gibt mehrere Gründe, warum die verkettete Liste kann mehr als eine addrinfo Struktur aufweisen, einschließlich: der Netzwerk-Host mehrfach vernetzt ist, zugänglich über mehrere Protokolle (zum Beispiel beide AF_INET und AF_INET6); oder derselbe Dienst ist von mehreren Socket-Typen verfügbar (z. B. eine SOCK_STREAM-Adresse und eine andere SOCK_DGRAM-Adresse). Normalerweise sollte die Anwendung versuchen, die Adressen in der Reihenfolge zu verwenden, in der sie zurückgegeben werden. Die in getaddrinfo() verwendete Sortierfunktion ist in RFC 3484 definiert; Die Reihenfolge kann für ein bestimmtes System durch Bearbeiten von /etc/gai.conf (verfügbar seit glibc 2.5) optimiert werden.

+1

Das Ausführen von 'connect' in der Schleife funktioniert nur, wenn Sie entweder eine Adressfamilie (IPv4 oder IPv6) erzwingen oder' AI_V4MAPPED' verwenden, um beide zu behandeln. Andernfalls müssen Sie einen 'Socket' mit der richtigen Adressfamilie für jede Adresse, die Sie versuchen, schließen und wieder öffnen. –

+0

@R .. Du hast Recht. Hinzufügen zur Antwort. – edmz

Verwandte Themen