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?
Antwort
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.
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.
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. –
@R .. Du hast Recht. Hinzufügen zur Antwort. – edmz
- 1. Welche Syntax sollte für WebMessageBodyStyle.Wrapped verwendet werden?
- 2. Datenbankschemaänderungen werden jährlich benötigt. Welche Strategie sollte verwendet werden?
- 3. Welche von IsDBNull und IsNull sollte verwendet werden?
- 4. Quellcodeverwaltung: Welche Versionsnummerierung sollte für Verzweigungen verwendet werden?
- 5. Welche Technik sollte verwendet werden, um 2d Kollisionsprüfungen zu bereinigen?
- 6. Wann sollte WS_EX_NOREDIRECTIONBITMAP verwendet werden?
- 7. Welche NSDataReadingOptions sollte beim Lesen einer lokalen Datei verwendet werden?
- 8. Sollte ViewData niemals verwendet werden?
- 9. Wo sollte Rx verwendet werden?
- 10. Welche Textboxereignisse sollten verwendet werden
- 11. DLIB: welche Eingabeargumente in draw_rectangle verwendet werden()
- 12. Wann sollte Flask.g verwendet werden?
- 13. Wann sollte $ .extend ({...}) verwendet werden?
- 14. Wann sollte wkWebView verwendet werden?
- 15. Wann sollte FOUNDATION_EXPORT verwendet werden?
- 16. Wann sollte StringBuilder verwendet werden?
- 17. Welche Datenstruktur soll verwendet werden?
- 18. Welche Merge-Strategien werden verwendet?
- 19. Wann sollte range.value verwendet werden?
- 20. Wann sollte ein neuer Ausnahmetyp verwendet werden?
- 21. Wann sollte in Rust inline verwendet werden?
- 22. Sollte PHP_EOL in E-Mails verwendet werden?
- 23. Wann sollte assert() in Matlab verwendet werden?
- 24. Sollte MEF in einer Produktionsanwendung verwendet werden
- 25. Sollte mailto in HTML5 verwendet werden?
- 26. Wann sollte StringProperty über String verwendet werden?
- 27. Welche String-Klassen werden in C++ verwendet?
- 28. Welche Datenstrukturen werden in Voltdb verwendet?
- 29. Welche TextFieldDelegate-Methode sollte aufgerufen werden?
- 30. Welche sollte welche erben?
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
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
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