linux c domain name to ip function gethostbyname returns structure hostent

In linux network programming, the gethostbyname function can directly obtain the ip address related information through the domain name url. It returns a structure named hostent. After querying the man gethostbyname manual, it is found that the structure is as follows

 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 */

The first four members of this structure are easy to understand,

h_name is the name of the server. For example, if you open www.baidu com, the corresponding h_name is www.a.shifen.com

h_aliases is the domain name used by the server for load balancing,

h_addrtype indicates the version number of the ip address, ipv4 and ipv6,

The obstacle to understanding is h_addr_list, which is a pointer to a character pointer, but only the first member is meaningful, h_addr_list [0], set h through macro definition_ Addr is named h_addr_list[0],

In fact, this pointer points to an in_ The address of the structure of addr can be converted by forced type conversion (struct in_addr *) H - > H_ Addr gets the structure. And struct in_ The addr structure is defined as follows

 struct in_addr {
               in_addr_t s_addr;
           };

There is only one member variable, ni_addr_t is actually an int type, named Ni through the macro definition_ addr_ t. It is estimated that there are different lengths on different hardware platforms, and s_addr is actually the value after converting the ip address composed of dotted decimal into decimal digits.

Let's verify it through a small program

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
int main (int argc, char *argv[])
{
	struct hostent *h;
	/* Detect whether the parameters in the command line exist */
	if (argc != 2) { 
	  /* If there are no parameters, the usage method is given */
	  printf ("usage: getip address\n");
	  /* Then exit */
	  exit(1);
	}
	
	/* Get host information */
	if ((h=gethostbyname(argv[1])) == NULL){
		/* If gethostbyname fails, an error message is given */
		herror("gethostbyname");
		/* Then exit */
		exit(1);
	}
	/* Print the information obtained by the program */
	printf("h_name: %s\n", h->h_name);
	printf("h_aliases: %s\n", h->h_aliases[0]);
	printf("h_addrtype: %d\n", h->h_addrtype);
	printf("h_length: %d\n", h->h_length);
	struct in_addr *inaddr;
	inaddr = (struct in_addr *)h->h_addr;
	printf("IP Address: %x\n",inaddr->s_addr);
	
	
	/* return */
	return 0;
 

compile

gcc  tes.c   -o tes.bin

implement

./tes.bin  www.baidu.com

result:

h_name: www.a.shifen.com
h_aliases: www.baidu.com
h_addrtype: 2
h_length: 4
IP Address: 69a9873d

The ip address above is not in the form of dotted decimal string, but in hexadecimal form already arranged in bytes.
There will be a very confusing place here, which involves the storage of characters and integers in linux. The storage rule in linux system is small segment storage, that is, a segment of numbers or characters with small weight are stored in the low part of the address, and those with high weight are stored in the high part of the address. All data and characters are stored in the direction of address growth.

For example, 69 a9 87 3d in the address, if it is arranged from low to high, it will be

3d, 87, a9, 69

See that? Through an applet to verify the following, add the above code to the following function
 

void show(int x)
{
	int a, b, c, d;
	a = x&0xff000000;
	a>>=24;
	b = x&0x00ff0000;
	b>>=16;
	c = x&0x0000ff00;
	c>>=8;
	d = x&0x000000ff;
	
	printf("%x %x %x %x\n", a, b, c, d);	
}

The function of this function is to expand the integer variable x according to the byte length

After adding, it is as follows:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>\
void show(int x);
 
int main (int argc, char *argv[])
{
	struct hostent *h;
	/* Detect whether the parameters in the command line exist */
	if (argc != 2) { 
	  /* If there are no parameters, the usage method is given */
	  printf ("usage: getip address\n");
	  /* Then exit */
	  exit(1);
	}
	
	/* Get host information */
	if ((h=gethostbyname(argv[1])) == NULL){
		/* If gethostbyname fails, an error message is given */
		herror("gethostbyname");
		/* Then exit */
		exit(1);
	}
	/* Print the information obtained by the program */
	printf("h_name: %s\n", h->h_name);
	printf("h_aliases: %s\n", h->h_aliases[0]);
	printf("h_addrtype: %d\n", h->h_addrtype);
	printf("h_length: %d\n", h->h_length);
	struct in_addr *inaddr;
	inaddr = (struct in_addr *)h->h_addr;
	printf("IP Address: %x\n",inaddr->s_addr);
	
	
	show(inaddr->s_addr);
	/* return */
	return 0;
}
 
 
void show(int x)
{
	int a, b, c, d;
	a = x&0xff000000;
	a>>=24;
	b = x&0x00ff0000;
	b>>=16;
	c = x&0x0000ff00;
	c>>=8;
	d = x&0x000000ff;
	
	printf("%x %x %x %x\n", a, b, c, d);	
}
 

The results are as follows:

h_name: www.a.shifen.com
h_aliases: www.baidu.com
h_addrtype: 2
h_length: 4
IP Address: 7da9873d
7d a9 87 3d

After the hexadecimal number is expanded, it is arranged at the small end.

Tags: C Linux TCP/IP

Posted on Sat, 30 Oct 2021 01:42:38 -0400 by AngelGSD