linux network programming (detailed explanation of getaddrinfo and gethostbyname functions)

1, getaddrinfo

Function prototype: int getaddrinfo(const char *node, const char *service, const struct addrinfo *hints, struct addrinfo **res);
Function function: according to hints The specified parameter requires that the server be obtained node And store the obtained results in res in
 Function parameters: node The domain name of the server or IP address
          service Decimal port string or protocol type of the service, such as "8099"“ http"
          hints Enter parameters to specify the parameters for obtaining server information
          res Store returned server information
 Return value: 0 is returned for success, and the corresponding error information is returned for failure

The struct addrinfo structure is as follows:

struct addrinfo {
   int              ai_flags;
   int              ai_family;
   int              ai_socktype;
   int              ai_protocol;
   socklen_t        ai_addrlen;
   struct sockaddr *ai_addr;
   char            *ai_canonname;
   struct addrinfo *ai_next;
};

Before the getaddrinfo function, you usually need to set the following six parameters: nodename, servname, and AI of hints_ flags,ai_family,ai_socktype,ai_protocol.

ai_flags is used to specify how to handle addresses and names. There are three values:

  • AI_PASSIVE when this flag is set, it indicates that the caller will use the returned address structure in the bind() function call. When this flag is not set, it indicates that it will be used in the connect() function call.
    When the node name bit is NULL and this flag is set, the returned address will be the wildcard address.
    If the node name is NULL and this flag is not set, the returned address will be the loopback address.
  • ai_cannoname when this flag is set, the AI in the first addrinfo structure returned by the function_ The cannoname member should contain a string ending with an empty character. The content of the string is the normal name of the node name.
  • AI_NUMERICHOST when this flag is set, this flag indicates that the node name in the call must be a numeric address string.

In the development of WiFi products, our common scenario is to resolve the ip address used by the host according to the host's domain name, ai_flags is usually set to 0.

ai_family is used to specify the IP address type corresponding to the domain name to be resolved, which can be IPv4 or IPv6. If you do not know the IP type corresponding to the host domain name, you can set this parameter to AF_UNSPEC, whose parameters are as follows:

  • AF_INET protocol type is IPv4
  • AF_INET6 protocol type is IPv6
  • AF_UNSPEC does not specify a protocol type

ai_protocol is used to specify the protocol type, ai_family can only specify IPv4 or IPv6, ai_protocol is more detailed and can be specified as TCP, UDP, IP, etc. the specific values are as follows:

  • IPPROTO_ IP protocol
  • IPPROTO_ IPv4 protocol
  • IPPROTO_IPV6 IPv6 protocol
  • IPPROTO_ UDP protocol
  • IPPROTO_TCP TCP protocol

ai_socktype is used to specify the data type of the protocol. Its values are as follows:

  • SOCK_STREAM data stream, corresponding to TCP protocol
  • SOCK_DGRAM datagram, corresponding to UDP protocol

The remaining parameters are not used in the hints parameter of the getaddrinfo function and do not need to be set.

The server information returned by the getaddrinfo function is stored in the res variable. A domain name can correspond to multiple IP addresses, so the addrinfo structure is a linked list, and all IP address information can be obtained by traversing the linked list.

Example:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int PhaseServerAddr(char *host)
{
	int rc = -1;
	char *ip;
	struct addrinfo *result = NULL;
	struct addrinfo hints = {0, AF_UNSPEC, SOCK_STREAM, IPPROTO_TCP, 0, NULL, NULL, NULL};

    if ((rc = getaddrinfo(host, NULL, &hints, &result)) == 0)
	{
		struct addrinfo* res = result;

		printf("AF_INET:%d\r\n",AF_INET);
		while (res)
		{

			ip = inet_ntoa(((struct sockaddr_in*)(res->ai_addr))->sin_addr);
			printf("ip type:%d addr:%s\r\n",res->ai_family,ip);
			res = res->ai_next;
		}
		freeaddrinfo(result);
	}
}

int main()
{
	PhaseServerAddr("www.baidu.com");
}

Execution results:

Put the obtained IP address into the browser, or you can directly open Baidu's home page.

2, gethostbyname

Function prototype: struct hostent *gethostbyname(const char *name);
Function function: resolve according to domain name IP address
 Function parameters: name Domain name, such as“ www.baidu.com"
Return value: successfully returned to storage IP The structure of the address. Failure is returned NULL

The prototype of struct host structure is:

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 */
}
  • h_name: Official domain name. The official domain name represents a home page, but in fact, the domain names of some famous companies are not registered with the official domain name.
  • h_aliases: alias. You can access the same host through multiple domain names. Multiple domain names can be bound to the same IP address, so other domain names can be specified in addition to the current domain name.
  • h_addrtype: indicates the address type of the server. IPv4 corresponds to AF_INET, IPv6 corresponds to AF_INET6.
  • h_length: saves the length of the IP address. IPv4 is 4 bytes long and IPv6 is 16 bytes long.
  • h_addr_list: stores the IP address corresponding to the domain name. A domain name can correspond to multiple IP addresses.

Example:

void PhaseServer()
{
	char **ptr;
	struct hostent *hst;
	char str[16];
	hst = gethostbyname("www.baidu.com");
	if(NULL != hst)
	{
		printf("offical name:%s\r\n",hst->h_name==NULL?"NULL":hst->h_name);

		for(ptr = hst->h_aliases;*ptr != NULL;ptr++)
		{
            printf(" alias:%s\r\n",*ptr);
		}

		switch(hst->h_addrtype) 
		{
			case AF_INET:
			case AF_INET6:
			ptr=hst->h_addr_list;

			for(;*ptr!=NULL;ptr++)
			{
				char *p = inet_ntop(hst->h_addrtype, *ptr, str, sizeof(str));
			    if(NULL != p)
					printf(" address:%s\r\n", p);
			}
			break;
			default:
			printf("unknown address type/n");
			break;
		}

	}
}

Operation results:

Keywords: Linux network socket

Added by GSHelpBoy on Sat, 01 Jan 2022 19:00:36 +0200