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