• 英文小册原文地址:​​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地址(是的,它们可以有多个),请使用此字段。

返回值

成功时返回指向​​struct hostent​​​结果的指针,错误时返回 ​​NULL​​。

和之前介绍过的其他函数不同,当发生错误时,它不设置​​errno​​​变量,而是将全局整数变量​​h_errno​​​设置为在头文件​​<netdb.h>​​中定义的常值。

例子

// 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);

参见

​​getaddrinfo()​​, ​​getnameinfo()​​, ​​gethostname()​​, ​​errno​​, ​​perror()​​, ​​strerror()​​, ​​struct in_addr​​