getaddrinfo

Die Funktion getaddrinfo() löst Funktionen wie gethostbyname() oder gethostbyaddr() ab und ist quasi “die” Schnittstelle zur DNS Auflösung eines Systems im Netzwerk.

Blöd nur, dass Windows 95 davon nichts wusste…


Fehlkonstruktion gethostbyname

gethostbyname() ist auch eine von diesen dummen Funktionen, die C Programmen ihren schlechten Ruf beschert hat. Hier wird nämlich das Ergebnis in einen Puffer im Hintergrund geschrieben, den man nicht unter Kontrolle hat.
Im schlimmsten Fall ist es ein globaler Puffer, was bedeutet, dass nicht zwei Threads die Funktion nicht gleichzeitig benutzen dürfen.

Das kann man jetzt gerne über einen Mutex lösen, durch niemand weiß, ob nicht eine Fremdbibliothek ebenso die Funktion aufruft und dort ohne Mutex den Puffer bearbeitet.

getaddrinfo() ist die flexibler Nachfolger-Funktion und allokiert separaten Speicher für jeden Aufruf. Außerdem erlaubt sie wesentlich mehr Optionen für die Hostnamen-Auflösung.

Warum als nicht immer getaddrinfo?

Tja, heute kein Thema. Jedes OS hat die Funktion integriert. Doch meine (Support-)Welt beginnt in den 90ern, wo getaddrinfo weder in Windows noch in den damaligen Unix-Derivaten garantiert vorhanden war.

Aus diesem Grund findet man in meinen älteren Projekten nur Mutex-geschützte gethostbyname Aufrufe.

Unter Windows wurde getaddrinfo() mit Windows XP in die ws2_32.dll integriert. Windows 2000 und ältere Vertreter meldeten somit immer einen fehlenden Einsprungpunkt, wenn man sein Projekt gegen die Funktion linken ließ.

Es gibt zwar den dokumentierten Verweis zur inline Funktion WspiapiGetAddrInfo, die getaddrinfo dann über andere DLLs zu laden versucht, doch auch die sind nur unter Windows 2000 mit bestimmten Preview-Updates vorhanden und nicht in Standard-Installationen.
Windows 9x fällt übrigens generell flach bei dem Thema.

Fazit

Heute baue ich in der Regel auf ein dynamisch geladenes getaddrinfo().

Ist die Funktion im OS enthalten (also LoadLibrary("ws2_32") oder dlopen(NULL, RTLD_GLOBAL)), wird sie benutzt.
Wenn nicht, dann implementiere ich sie mit gethostbyname provisorisch inklusive Mutex nach.

Auf diese Weise kommen Binaries heraus, die überall gestartet werden können und dann eben das heranziehen, was vorhanden ist.