主页 > imtoken钱包安卓版下载步骤 > etc的原理 获取主机名、IP——gethostent()、gethostbyname()

etc的原理 获取主机名、IP——gethostent()、gethostbyname()

1.原理:查询/etc/hosts等文件和DNS或NIS服务器

由 gethostbyname() 和 gethostbyaddr() 执行的域名查询使用任何或所有名称服务器 named(8)、来自 /etc/hosts 的虚线和网络信息服务(NIS 或 YP)的组合,取决于 /etc/host.conf 中命令行的内容。 默认操作是查询 named(8),然后是 /etc/hosts。(ubuntu 手册页)

这些函数返回的网络配置信息可以保存在很多地方。 它们可以保存在静态文件(/etc/hosts、/etc/services 等)中,也可以由名称服务管理,例如 DNS(域名系统)或 NIS(网络信息服务)。

二、说明:

1) gethostbyname*() 和 gethostbyaddr*() 已过时,改用 getaddrinfo() 和 getnameinfo()

gethostbyname*() 和 gethostbyaddr*() 函数已过时。 应用程序应该改用 getaddrinfo(3) 和 getnameinfo(3)。

POSIX.1-2001 指定了 gethostbyname()、gethostbyaddr()、sethostent()、endhostent()、gethostent() 和 h_errno;

gethostbyname()、gethostbyaddr() 和 h_errno 在该标准中被标记为过时。

POSIX.1-2008 删除了 gethostbyname()、gethostbyaddr() 和 h_errno 的规范,建议改用 getaddrinfo(3) 和 getnameinfo(3)。

(ubuntu 手册页)

gethostbyname 和 gethostbyaddr 函数仅支持 IPv4。 解析 IPv6 地址的 API 经历了几次迭代,将在第 11.20 节中描述; 最终结果是 getaddrinfo 函数。 (UNIX网络编程第1卷,第三版)

2) 只返回一个指向静态数据区的指针

gethostbyname 返回的值指向库中的静态结构。 在进行进一步的 gethostbyname 、 gethostbyaddr 或 gethostent 调用之前etc的原理etc的原理,您必须从该结构中复制信息。

(ubuntu 手册页)

3)

4)gethostent():获取host文件中的下一个条目,即每次都获取下一个条目,所以程序通常使用while循环获取所有条目

----------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 from name server.  */
#if defined __USE_MISC || defined __USE_GNU
# define	h_addr	h_addr_list[0] /* Address, for backward compatibility.*/
#endif
};

----------gethostent()

/**
 * gethostent()
 * OS: Ubuntu 11.04 Server
 */
#include 
#include 
#include 
#include 	// inet_ntop()
static void printhost(struct hostent *host);
int
main(int argc, char *argv[])
{
	struct hostent *host = NULL;
	sethostent(1);
	while( (host = gethostent()) != 0 )
	{
		printhost(host);
		printf("\n");
	}
	endhostent();
	return EXIT_SUCCESS;
}
static void printhost(struct hostent *host)
{
	char **aliases = NULL;
	char **addr_list = NULL;
	char addr_p[INET_ADDRSTRLEN];	// IPv4
	
	/* print host name and aliases */
	printf("hostname: %s\n", host->h_name);
	for(aliases = host->h_aliases; *aliases; aliases++)
	{
		printf("alternate name: %s\n", *aliases);
	}
	
	/* print address type and length */
	if(host->h_addrtype == AF_INET)
	{
		printf("address type: AF_INET\n");
	}
	else
	{
		printf("Not an IPv4 address.\n");
	}
	printf("address length: %d\n", host->h_length);
	
	/* print address list */
	//printf("%d\n", sizeof(*(host->h_addr_list)));
	printf("%x\n", *(int *)(*(host->h_addr_list)));
	for(addr_list = host->h_addr_list; *addr_list; addr_list++)
	{
		printf("address: %s\n", inet_ntop(host->h_addrtype, *addr_list, addr_p, INET_ADDRSTRLEN));
	}
}
/*
hostname: localhost
address type: AF_INET
address length: 4
100007f
address: 127.0.0.1
hostname: Ubuntu-Server.localdomain
alternate name: Ubuntu-Server
address type: AF_INET
address length: 4
101007f
address: 127.0.1.1
hostname: ip6-localhost
alternate name: ip6-loopback
address type: AF_INET
address length: 4
100007f
address: 127.0.0.1
*/

Q:为什么只能获取IP 127.0.0.1?

A:/etc/hosts文件内容如下:

127.0.0.1       localhost
127.0.1.1       Ubuntu-Server.localdomain       Ubuntu-Server
...

这与这组函数的工作原理有关

----------gethostbyname()

/**
 * gethostbyname()
 * OS: Ubuntu 11.04 Server
 */
#include 
#include 
#include 
#include 	/* inet_ntop() */
int main(int argc, char *argv[])
{
	struct hostent *h_ent = NULL;
	char addr_p[INET_ADDRSTRLEN];
	char **addr_list = NULL;
	
	/* Verify a "hostname" parameter was supplied */
	if(argc != 2)
	{
		printf("please input the hostname.\n");
		exit(EXIT_FAILURE);
	}
	
	/* call gethostbyname() with a host name. gethostbyname() returns a pointer to a hostent struct or NULL. */
	h_ent = gethostbyname(argv[1]);
	if(h_ent == NULL)
	{
		printf("%s was not resolved.\n", argv[1]);
		exit(EXIT_FAILURE);
	}
	
	for(addr_list = h_ent->h_addr_list; *addr_list; addr_list++)
	{
		inet_ntop(AF_INET, *(addr_list), addr_p, INET_ADDRSTRLEN);
		printf("hostname: %s, was resolved to: %s\n", argv[1], addr_p);
	}
	return 0;
}
/*
$ ./a.out baidu.com
hostname: baidu.com, was resolved to: 220.181.111.85
hostname: baidu.com, was resolved to: 220.181.111.86
hostname: baidu.com, was resolved to: 123.125.114.144
add a line in /etc/hosts:
111.111.111.111 baidu.com
$ ./a.out baidu.com
hostname: baidu.com, was resolved to: 111.111.111.111
*/

Q:为什么修改/etc/hosts后会出现以上结果?

答:由 gethostbyname() 和 gethostbyaddr() 执行的域名查询使用任何或所有名称服务器 named(8)、/etc/hosts 的虚线和网络信息服务(NIS 或YP),取决于 /etc/host.conf 中命令行的内容。 (ubuntu 手册页)

/etc/host.conf文件内容如下:

# The "order" line is only used by old versions of the C library.
order hosts,bind
multi on

主机文件优先

----------gethostbyaddr()

/**
 * gethostbyaddr()
 * OS: Ubuntu 11.04 Server
 */
#include 
#include 
#include 
#include 	/* inet_pton() */
int main(int argc, char *argv[])
{
	struct hostent *h_ent = NULL;
	char addr_n[sizeof(struct in_addr)];	// or struct in_addr addr_n;
	int status;
	
	/* Verify a "ip address" parameter was supplied */
	if(argc != 2)
	{
		printf("please input the ip address.\n");
		exit(EXIT_FAILURE);
	}
	
	status = inet_pton(AF_INET, argv[1], addr_n);
	if(status == 0)	// invalid format
	{
		printf("The format of the ip address is invalid.\n");
		exit(EXIT_FAILURE);
	}
	else if(status == -1)
	{
		printf("error: inet_pton\n");
		exit(EXIT_FAILURE);
	}
	
	/* call gethostbyaddr() */
	h_ent = gethostbyaddr(addr_n, sizeof(struct in_addr), AF_INET);
	if(h_ent == NULL)
	{
		printf("error: gethostbyaddr\n");
		exit(EXIT_FAILURE);
	}
	
	printf("%s was resolved to hostname: %s\n", argv[1], h_ent->h_name);
	
	return 0;
}
/*
$ ./a.out 220.181.111.85	# baidu.com
error: gethostbyaddr
add a line in /etc/hosts:
111.111.111.111 baidu.com
$ ./a.out 111.111.111.111
111.111.111.111 was resolved to hostname: baidu.com
*/