The gethostbyname() function is used in C programming to retrieve information about a host computer given its hostname. Though this function is now considered obsolete and replaced by the getaddrinfo() function, gethostbyname() is still widely used due to its simplicity.

In this comprehensive guide, we will cover everything you need to know about using the gethostbyname() function in C, including:

  • What is the gethostbyname() function and why is it used
  • The syntax and parameters of gethostbyname()
  • How gethostbyname() works
  • The hostent structure returned by gethostbyname()
  • How to check for and handle errors
  • Examples of using gethostbyname()
  • Why gethostbyname() is now considered obsolete
  • Alternatives to gethostbyname()

What is Gethostbyname() and Why Use It?

The gethostbyname() function is used to retrieve information about a host computer based on its hostname. Specifically, gethostbyname() takes a hostname string as a parameter and returns a pointer to a hostent structure containing information such as:

  • Official hostname
  • Alias hostnames
  • Address family (IPv4/IPv6)
  • IP address(es)
  • Address length

This information is useful when writing network applications, as you can lookup a computer‘s IP address and other details by hostname. The hostname is often more convenient to work with compared to directly using IP addresses.

Here are some examples of why you may use gethostbyname():

  • Looking up the IP address(es) for a host to open a socket connection
  • Resolving a hostname entered by the user to an IP address
  • Printing out official host details given a hostname string
  • Learning about a host‘s multiple alias names and addresses

So in summary, it provides a simple way to get essential host details needed for tasks like making connections by hostname.

Syntax and Parameters

Here is the syntax and parameters for the gethostbyname() function:

struct hostent *gethostbyname(const char *name);

Parameters:

  • name – The hostname to lookup. This should be a null-terminated string.

Return Value

  • Pointer to a hostent structure on success
  • NULL pointer on failure (Sets h_errno error code)

To use gethostbyname() you need to include the netdb.h header which defines the hostent structure.

How Gethostbyname() Works

When you call gethostbyname() and pass a hostname string, here is a high-level overview of what happens:

  1. The function asks the DNS resolver subsystem to lookup the IP address for the given hostname.
  2. The DNS resolver queries the DNS servers to resolve the hostname to IP address(es).
  3. On success, gethostbyname() returns a pointer to a hostent structure containing the host details.
  4. On failure, gethostbyname() returns NULL and sets the h_errno error code.

Internally, gethostbyname() utilizes DNS and your systems resolver configuration to retrieve the host data. The hostent structure is populated with information returned by the DNS lookup.

If multiple IP addresses exist for the hostname, the hostent structure will contain a list of addresses.

The Hostent Structure

The most essential piece to understand is the hostent structure that is returned by gethostbyname() on success.

Here is the definition of struct hostent:

struct hostent {
   char  *h_name;        /* official name of host */
   char **h_aliases;     /* alias list */
   int    h_addrtype;    /* host address type */
   int    h_length;      /* length of address */
   char **h_addr_list;   /* list of addresses */
}
#define h_addr  h_addr_list[0] /* for backward compatibility */

Let‘s take a quick look at what each field contains:

  • h_name: The official/primary hostname
  • h_aliases: Null-terminated array of alternate hostname aliases
  • h_addrtype: Host address type (AF_INET for IPv4, AF_INET6 for IPv6)
  • h_length: Length in bytes of each address
  • h_addr_list: Array of pointers to IP address strings (null terminated)
  • h_addr: Pointer to first IP address (for back-compat access)

So in summary, this structure stores the primary hostname, aliases, address type/length, and contains pointers to access the IP addresses.

Accessing the hostent data is simple. For example if hostptr points to the returned structure:

  • hostptr->h_name – Official hostname
  • hostptr->h_addr_list[0] – First IP address

Now that we understand the host structure, let‘s look at some examples of using gethostbyname().

Example 1: Basic Gethostbyname Usage

This simple example demonstrates looking up the IP address for "www.google.com":

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>

int main(void) {

  struct hostent *host_info;

  host_info = gethostbyname("www.google.com");

  if(host_info == NULL) {
    herror("gethostbyname");
    exit(1);
  }

  printf("Official name: %s \n", host_info->h_name);

  printf("IP Address 1: %s\n",inet_ntoa(*(struct in_addr *)host_info->h_addr));

  return 0;
}

The steps are:

  1. Include netdb.h and declare host_info hostent pointer
  2. Call gethostbyname() to lookup IP
  3. Check if NULL and print error
  4. If valid, print out hostname and IP address fields

Running this should print out details for www.google.com like:

Official name: www.google.com  
IP Address 1: 172.217.7.206

Easy enough! The true power though comes from accessing the other data or handling multiple addresses.

Example 2: Print Multiple IP Addresses

If a host has multiple IP addresses associated, you can print them out like this:

#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(void) {

  int i;
  struct hostent *host_info;

  host_info = gethostbyname("www.example.com");

  if(host_info == NULL) {
    herror("gethostbyname"); 
    exit(1);
  }

  printf("Host name: %s \n", host_info->h_name);

  for(i = 0; host_info->h_addr_list[i] != NULL; i++) {
     printf(" IP addr %d: %s\n", i+1, 
        inet_ntoa(*(struct in_addr *)host_info->h_addr_list[i]) );
  }

  return 0;
}

This loops through h_addr_list printing out each IP address for the hostname. So you may get output like:

Host name: www.example.com
 IP addr 1: 93.184.216.34
 IP addr 2: 2606:2800:220:1:248:1893:25c8:1946

The same concept could be used to print out alias hostnames or other fields.

Checking for Errors

Since gethostbyname() returns NULL on failure, checking if it succeeded is done like this:

hostptr = gethostbyname(hostname);

if(hostptr == NULL) {
  // Handle error
} else {
  // Proceed to use hostent data 
}

The specific error code is set in the global h_errno variable. So you can additionally print or examine this like:

if(hostptr == NULL) {

  fprintf(stderr, "Error %d looking up hostname: %s\n", h_errno, hostname);

  if(h_errno == TRY_AGAIN) {
    // Retry lookup
  } else { 
    exit(1); 
  }

}

Some common h_errno codes you may see:

  • NO_RECOVERY – Non-recoverable DNS error
  • TRY_AGAIN – DNS query timeout, retry may work
  • NO_ADDRESS – No IP address exists for hostname

See the netdb.h header for other codes.

Handling and logging these errors is vital to writing robust code using gethostbyname().

Why Gethostbyname() is Now Obsolete

While gethostbyname() is still in widespread use, it is technically obsolete (deprecated). There are a few core reasons a modern replacement is needed:

1. IPv6 Support – gethostbyname() pre-dates IPv6. A new function was needed with IPv6 integrated. It returns IPv4-only structures.

2. Thread-Safety – The hostent structure returned by this function is static/non-reentrant. This causes issues with thread safety.

3. Limited Error Handling – Error reporting functionality via h_errno is relatively limited.

The modern replacement function getaddrinfo() properly handles all the above issues.

Despite the technical obsolescence, many systems and codebases still rely on gethostbyname() when IPv4 support is sufficient. It may take quite some time for displacement given how widely used it is.

Alternatives to Gethostbyname()

Now we‘ll briefly cover how to modernize code to use the replacement for gethostbyname() – the getaddrinfo() function.

Getaddrinfo() Usage Example:

#define _GNU_SOURCE
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main(void) {

  struct addrinfo hints;
  struct addrinfo *result, *rp;

  // Set criteria for hostname lookup
  memset(&hints, 0, sizeof(struct addrinfo));
  hints.ai_family = AF_INET;    /* IPv4 only */

  // Lookup hostname 
  int s = getaddrinfo("www.wikipedia.org", NULL, &hints, &result);

  // Handle errors
  if (s != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
    return 1;
  } 

  // Print out IP addresses
  for(rp = result; rp != NULL; rp = rp->ai_next) {
     void *addr;
     char ipstr[INET6_ADDRSTRLEN];  

     // Convert IPv4/v6 binary address to string for printing 
     addr = &((struct sockaddr_in *) rp->ai_addr)->sin_addr;  
     inet_ntop(rp->ai_family, addr, ipstr, sizeof(ipstr));

     printf(" %s\n", ipstr);
  }

  // Clean up
  freeaddrinfo(result);

  return 0;
}

The improvements with getaddrinfo() are:

  • Dual IPv4/IPv6 support
  • Additional error reporting via gai_strerror()
  • Threaded DNS query capability
  • ai_next linked list for multiple address returns

For simple IPv4 address lookups though, gethostbyname() is still simpler compared to the more advanced getaddrinfo() interface.

So in summary – getaddrinfo() fixes technical limitations, but gethostbyname() remains the easier method in basic use cases.

Conclusion

That wraps up our deep dive on gethostbyname(). Here are some key points about this essential C networking function:

  • It resolves hostnames to IP address and returns a hostent structure
  • hostent contains officially assigned hostname, aliases, address type/length, and IP addresses
  • Simple interface takes just a hostname string and returns host details
  • Technically obsolete due to IPv6, threading, error handling limitations
  • Very common in existing IPV4 applications due to simplicity
  • For new code, consider the improved getaddrinfo()

I hope you found this comprehensive guide useful! You should now understand the core mechanics of gethostbyname() and how to properly utilize it within your C programs.

Let me know if you have any other questions on this or other network programming topics!

Similar Posts