本文使用的glibc版本是2.19
1.GNU LIB C 手册[http://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/pdf/libc.pdf]
其实这算是LINUX下C语言的库函数手册,大部分函数的简单说明都能在里面查到。另外,如果你的环境是在liunux下,会有更简单的办法,就是man命令请看后面的内容。另外,这个版本的libc其实是旧版本的,2.2版本。但是现在常用的已经是比这个版本高了(本文使用的已经是2.19了)。提供这个手册的其中一个原因也是为了让大家注意一下自己的libc版本,以免跟我一样被版本问题坑一下。查询版本方法(shell命令):
ldd --version
2.GNU LIB C 源文件[http://ftp.gnu.org/gnu/libc/glibc-2.19.tar.xz]
注意:http://ftp.gnu.org里存的基本都是和GNU相关的东西,没事翻一番,或许有意外收获
这个结构类型并不是在libc里面有定义的,因此没法通过源代码找到这个函数的结构。但是也是有办法查到的,比如百度一下(= =),不过我赌五毛钱这么干的人会被坑一下。
我建议可以通过gdb编译的时候带上-g参数,然后在调试程序的时候打印类型
(gdb)ptype struct hostent
结果如下:
struct hostent {
char *h_name;
char **h_aliases;
int h_addrtype;
int h_length;
char **h_addr_list;char
}
host_name:该地址最终的名字
例如ping百度的时候,最终会指向www.a.shifen.com
h_aliases 地址的预备名称的指针,一般为空
h_addrtype 地址类型,一般是是AF_INET。
h_length – 地址的长度,AF_INET时是4,单位应该是字节
h_addr_list -主机网络地址指针。存的就是我们要的IP地址。
现存的资料可能会提到一个成员char *h_addr 。但是根据我使用gdb打印的结果来看,这个成员已经不存在了。使用这个成员也会导致编译错误。
以下是可以在libc手册里查到的关于该函数的说明
Function
struct hostent * gethostbyname (const char *name)
The gethostbyname function returns information about the host named name. If the lookup fails, it returns a null pointer.
其实也可以在linux通过man命令查询到一些介绍,同时也可以查到使用该函数需要引入的头文件
man gethostbyname
在这里贴上源代码:
struct hostent *
gethostbyname(name)
const char *name;
{
struct hostent *hp;
if (__res_maybe_init (&_res, 0) == -1) {
__set_h_errno (NETDB_INTERNAL);
return (NULL);
}
if (_res.options & RES_USE_INET6) {
hp = gethostbyname2(name, AF_INET6);
if (hp)
return (hp);
}
return (gethostbyname2(name, AF_INET));
}
可以看到,主体实现其实还在另外一个函数gethostbyname2里。但是这个函数比较长,这里就不贴出来了,后面简单介绍一下就算了。有兴趣的可以下载源码查看[^footnote]
struct hostent * gethostbyname2 (const char *name, int af)
The gethostbyname2 function is like gethostbyname, but allows the caller to specify the desired address family (e.g. AF_INET or AF_INET6) of the result.
函数第二个参数是协议类型,可以是AF_INET(IPv4)或者AF_INET6(IPv6)类型
首先,上一段有问题的代码。对,你没看错,就是有问题的代码。
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
int main(void)
{
struct hostent *hostinfo;
char *hostname = "www.csdn.com"
hostinfo = gethostbyname (hostname);
if (hostinfo == NULL){
fprintf (stderr, "Unknown host %s.\n", hostname);
exit(EXIT_FAILURE);
}
printf("HostName:%s\n", hostinfo->h_name);
printf("IPAddress:%s",inet_ntoa(*((struct in_addr*)h->h_addr)));
}
注意最后一行代码
printf(“IPAddress:%s”,inet_ntoa(((struct in_addr)h->h_addr)));
在前面已经提过了,h_addr这个成员在新版本里已经被删除掉了。因此这里不能再使用这个成员了。其实可以使用另外一个成员h_addr_list。这是一个二维指针,其实IP地址就依次存在于
hostinfo->h_addr_list[0][0]
hostinfo->h_addr_list[0][1]
hostinfo->h_addr_list[0][2]
hostinfo->h_addr_list[0][3]
例如例子中,查询的是”www.csdn.com“的IP地址,如果是使用
ping www.csdn.com
返回的值可能是:114.112.73.194
那么对应存的值是
hostinfo->h_addr_list[0][0]//值为114
hostinfo->h_addr_list[0][1]//值为112
hostinfo->h_addr_list[0][2]//值为73
hostinfo->h_addr_list[0][3]//值为194,有符号打印则结果为负数
本来是想用inet_ntoa函数转换的,但是这个函数好像也经过了修改,gcc编译的时候会警报提示说” format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘int’“。但是在libc的源码中看到的inet_ntoa函数返回值又确实是char 类型的。我尝试直接将结果当成一个整数打印出来,但是也并没有看出点什么。有明白的朋友希望告知。