gethostbyaddr() 函数支持从 IP 地址获得主机信息,定义如下:
[C++] 纯文本查看 复制代码 #include <sys/socket.h> /* for AF_INET */
struct hostent *gethostbyaddr(const void *addr,
socklen_t len, int type);
第 1 个参数 addr 在 IPv4 的情况下指向一个 struct in_addr 的地址结构;第 2 个参数 len 表示第 1 个参数所指区域的大小,在 IPv4 情况下为 sizeof(struct in_addr),即 32 位;第 3 个参数 type 指定需要查询主机的 IP 地址的类型,在 IPv4 的情况下为 AF_INET。函数的返回值也是一个 struct hostent 指针结构。
gethostbyaddr() 和 gethostbyname() 都是不可重入函数,由于传出的值为一块静态的内存地址,因此当进行新的查询时,这块区域会被覆盖,所以在使用时要小心。
测试代码:
[C++] 纯文本查看 复制代码 #include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
int main(int argc, char *argv[])
{
struct hostent *he;
int i;
strlen(argv[1]);
struct in_addr my_addr;
my_addr.s_addr = inet_addr(argv[1]);
he = gethostbyaddr(&my_addr, sizeof(struct in_addr), AF_INET);
if (he != NULL)
{
printf("%s\n",he->h_name);
} else {
printf("Can not supoort reverse DNS query.\n");
}
return 0;
}
运行输出:# ./gethostbyaddr 149.20.20.133
pub1.kernel.org 这个过程实际上是一个反向DNS 查询过程,按照 DNS 的说法,gethostbyaddr() 在 in_addr.arpa 域中向一个名字服务器查询 PTR 记录。
PTR 记录称为”指针记录“(pointer record),它负责把 IP 地址映射成主机名。对于 IPv4 地址,32 位地址的 4 个字节先反转顺序,每个字节都转换成各自的十进制 ASCII 值(0~255)后,再添加上 in-addr.arpa,结果字符串用于 PTR 查询。比如用 dig 命令来查询上面的 149.20.20.133 这个 IP : # dig @8.8.8.8 -x 149.20.20.133
; <<>> DiG 9.7.0-P1 <<>> @8.8.8.8 -x 149.20.20.133
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38131
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;133.20.20.149.in-addr.arpa. IN PTR
;; ANSWER SECTION:
133.20.20.149.in-addr.arpa. 1167 IN CNAME 133.128-27.20.20.149.in-addr.arpa.
133.128-27.20.20.149.in-addr.arpa. 1169 IN PTR pub1.kernel.org.
;; Query time: 95 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Fri Jun 8 00:35:04 2012
;; MSG SIZE rcvd: 98
现在大部分的服务器地址都不设置反向查询功能,因此用上面的程序进行测试时,往往得到的返回结果为空。 |