函数gethostbyaddr取一个二进制的IP地址并试图找到相应于此地址的主机名,与gethostbyname的行为恰好相反。gethostbyname感兴趣的是h_name
其原型为:
#include <netdb.h>
struct hostent * gethostbyaddr(const char *addr, size_t len , int family);
参数addr不是char*类型, 而是一个真正指向含有IPv4或IPv6地址的结构in_addr或in6_addr,len是此结构的大小,对于 IPv4地址为4,对于IPv6地址为16,参数family为AF_INET或AF_INET6
函数gethostbyaddr和IPv6支持,因为gethostbyaddr总有一个地址族参数,所以当加上IPv6支持到BIND时,无需发明另一个函数(类型于函数gethostbyaddr2)。但是,当参数是IPv6地址时,仍有一些差别。下面的三个测试按步骤进行:
1、如果family是AF_INET6,len是16,且地址是IPv4映射的IPv6地址,则在域in_addr.arpa中查找地址的低32位(IP4地址部分)
2、如果family是AF_INET6,len是16,且地址是IPv4兼容的IPv6地址,则在域in_addr.arpa中查找地址的低32位(IPv4地址部分)
3、如果被查找的是IPv4地址(或参数family为AF_INET,或上述两种情况中的一个为真)且解析器选项RES_USE_INET6设置 ,则返回的地址(参数addr的一个拷贝)被转换为一个IPv4映射的IPv6地址,h_addrtype为AF_INET,h_length为16
代码如下:
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
int main(int argc, char **argv)
{
struct in_addr addr;
struct hostent *phost;
if (inet_pton(AF_INET, argv[1], &addr) <= 0) {
printf("inet_pton error:%s\n", strerror(errno));
return -1;
}
phost = gethostbyaddr((const char*)&addr, sizeof(addr), AF_INET);
if (phost == NULL) {
printf("gethostbyaddr error:%s\n", strerror(h_errno));
return -1;
}
printf("host name:%s\n", phost->h_name);
return 0;
}
当第二个参数为127.0.0.1时,查找的是/etc/hosts中的映射关系
输出为
当第二个参数为 180.97.33.108,输出为