Resolving DNS Hostnames
This article explains how to resolve a DNS hostname in a way that offers you maximum flexibility.
There are three primary APIs in OS X and iOS for resolving hostnames:
NSHost (only in OS X),
CFHost, and the POSIX resolver API.
NSHostis a common way to pass hostnames to other APIs, using
NSHostto resolve addresses yourself is generally discouraged because it is a synchronous API. Thus, using it on the main thread can cause serious performance degradation. Because this API is discouraged, its use is not described here.
CFHostAPI allows you to perform resolution asynchronously, and is the preferred way to resolve hostnames if you must resolve them yourself.
POSIX—The POSIX layer provides several functions for resolving hostnames. These functions should be used only if you are writing portable code that must be shared with non-Apple platforms or if you are integrating your code with existing POSIX networking code.
Resolving Hostnames with CFHost
To resolve a host with
CFHostRefobject by calling
CFHostSetClientand provide the context object of your choice and a callback function that will be called when resolution completes.
CFHostScheduleWithRunLoopto schedule the resolver on your run loop.
CFHostStartInfoResolutionto tell the resolver to start resolving, passing
kCFHostAddressesas the second parameter to indicate that you want it to return IP addresses.
Wait for the resolver to call your callback. Within your callback, obtain the results by calling
CFHostGetAddressing. This function returns an array of
CFDataRefobjects, each of which contains a POSIX
The process for reverse name resolution (translating an IP address into a hostname) is similar, except that you call
CFHostCreateWithAddress to create the object, pass
CFHostStartInfoResolution, and call
CFHostGetNames to retrieve the results.
Resolving Hostnames with POSIX Calls
If you intend to use POSIX calls to resolve hostnames, be aware that these calls are synchronous and should not be used on the main thread in a GUI app. Instead, you should either create a separate POSIX thread or a GCD task and perform these calls within that context.
POSIX defines three functions in
<netdb.h> for resolving hostnames:
Returns all the resolved addresses for a given hostname. This function is the preferred way to obtain address information at the POSIX level. You can find sample code in its man page (linked above).
Important: Some older DNS servers do not reply to IPv6 lookup requests with an error. The POSIX
getaddrinfofunction attempts to hide this misbehavior by canceling outstanding IPv6 queries shortly after receiving a successful IPv4 reply. If your app would benefit from continuing to receive IPv6 addresses until you connect successfully (rather than stopping as soon as you have an IPv4 address that might or might not work), then you should use an asynchronous API such as
Returns a single IPv4 address for a given hostname. This function is discouraged for new development because it is limited to IPv4 addresses.
Returns a single address for a given hostname in the specified address family (
AF_INET6, and so on).
Although this function allows you to get around the IPv4 limitations of
gethostbyname, it still limits your ability to try multiple addresses at once and choose the fastest one. Thus, this function is primarily intended as a nearly drop-in replacement for
gethostbynamein existing code. The
getaddrinfois preferred for use in new code.
For reverse name resolution (translating an IP address into a hostname), POSIX provides
getnameinfo function is preferred because it is more flexible.
To learn more about these functions, read their respective man pages, linked above.