- 英文小册原文地址:beej.us/guide/bgnet…
- 作者:Beej
- 中文翻译地址:www.chanmufeng.com/posts/netwo…
根据主机名获取IP地址,或者相反。
函数原型
#include <sys/socket.h>
#include <netdb.h>
struct hostent *gethostbyname(const char *name); // DEPRECATED!
struct hostent *gethostbyaddr(const char *addr, int len, int type);
说明
请注意:这两个函数已经由 getaddrinfo() 与 getnameinfo() 取而代之!实际上,gethostbyname() 无法在 IPv6 中正常运行。
这些函数可以转换 host name 与 IP addresse。例如:你可以用
gethostbyname()
取得其 IP address,并储存在
struct in_addr
。
反之,如果你有一个
struct in_addr
或
struct in6_addr
,你可以用
gethostbyaddr()
得到 hostname。
gethostbyaddr()
与 IPv6 相容,但是你最好使用新的
getnameinfo()
代替它。
(如果你有一个点分十进制格式的IP地址,你想要查询它的 hostname,你在使用
getaddrinfo()
时最好要搭配
AI_CANONNAME
标识)。
gethostbyname()
接收一个类似 "www.chanmufeng.com" 的字串,然后传回一个
struct hostent
,里面包含了超多的数据,包括了 IP address(其它的信息包括官方的 host name、一连串的别名、地址类型、地址长度、以及地址列表。这是个通用的资料结构,在特定的用途上使用起来也很方便)。
在
gethostbyaddr()
代入一个
struct in_addr
或
struct in6_addr
,然后就会返回给你一个相对应的 host name(如果有的话),它的作用和
gethostbyname()
正好相反。至于参数,
addr
是一个
char*
,你实际上想要用一个指向
struct in_addr
的指针;
len
应该被设置成
sizeof(struct in_addr)
,而
type
应为
AF_INET
。
所以这个
struct hostent
会返回什么呢?它有许多字段,包含 host 的相关数据。
字段 | 描述 |
char *h_name | 主机的规范(official、canonical)名字 |
char **h_aliases | 可以使用数组访问的别名列表,最后一个元素为NULL |
int h_addrtype | 结果的地址类型,出于我们的目的,它实际上应该是AF_INET。 |
int length | 以字节为单位的地址长度,对于IP(版本4)地址为4。 |
char **h_addr_list | 此主机的IP地址列表。虽然这是一个char**,但它实际上是一个伪装的structin_addr *s数组。最后一个数组元素为NULL。 |
h_addr | h_addr_list[0]的常用别名。如果你只是想要此主机的任何旧IP地址(是的,它们可以有多个),请使用此字段。 |
返回值
例子
// THIS IS A DEPRECATED METHOD OF GETTING HOST NAMES
// use getaddrinfo() instead!
#include <stdio.h>
#include <errno.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
int i;
struct hostent *he;
struct in_addr **addr_list;
if (argc != 2) {
fprintf(stderr,"usage: ghbn hostname\n");
return 1;
}
if ((he = gethostbyname(argv[1])) == NULL) { // get the host info
herror("gethostbyname");
return 2;
}
// print information about this host:
printf("Official name is: %s\n", he->h_name);
printf(" IP addresses: ");
addr_list = (struct in_addr **)he->h_addr_list;
for(i = 0; addr_list[i] != NULL; i++) {
printf("%s ", inet_ntoa(*addr_list[i]));
}
printf("\n");
return 0;
}
// THIS HAS BEEN SUPERCEDED
// use getnameinfo() instead!
struct hostent *he;
struct in_addr ipv4addr;
struct in6_addr ipv6addr;
inet_pton(AF_INET, "192.0.2.34", &ipv4addr);
he = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
printf("Host name: %s\n", he->h_name);
inet_pton(AF_INET6, "2001:db8:63b3:1::beef", &ipv6addr);
he = gethostbyaddr(&ipv6addr, sizeof ipv6addr, AF_INET6);
printf("Host name: %s\n", he->h_name);