😄 学了忘,忘了学,学了还得忘,忘了还得学,做个笔记先
利用域名获取IP地址
#include <netdb.h>
struct hostent *gethostbyname(const char *name);
struct hostent {
char *h_name; /* official name of host */
char **h_aliases; /* alias list */
int h_addrtype; /* host address type */
int h_length; /* length of address */
char **h_addr_list; /* list of addresses */
};
从上述结构体定义中可以看出,不只返回IP信息,同时还连带着其他信息。各位不用想得太过复杂。域名转IP时只需关注h_addr_list。
简要说明上述结构体各成员:
1️⃣ h_name
该变量中存有官方域名(Official domain name)。官方域名代表某一主页,但实际上,一些著名公司的域名并未用官方域名注册。
2️⃣ h_aliases
可以通过多个域名访问同一主页。同一IP可以绑定多个域名,因此,除官方域名外还可指定其他域名。这些信息可以通过h_aliases获得。
3️⃣ h_addrtype
gethostbyname函数不仅支持IPv4,还支持IPv6。因此可以通过此变量获取保存在h_addr_list的IP地址的地址族信息。若是IPv4,则此变量存有AF_INET。
4️⃣ h_length
保存IP地址长度。若是IPv4地址,因为是4个字节,则保存4;IPv6时,因为是16个字节,故保存16。
5️⃣ h_addr_list
这是最重要的成员。通过此变量以整数形式保存域名对应的IP地址。另外,用户较多的网站有可能分配多个IP给同一域名,利用多个服务器进行负载均衡。此时同样可以通过此变量获取IP地址信息。
调用gethostbyname函数后返回hsotent结构体的变量结构如图所示,该图在实际编程中非常有用,希望大家结合之前的hostent结构体定义加以理解。
下列示例主要演示gethostbyname函数的应用,并说明hostent结构体变量的特性。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
void error_handing(char *message);
int main(int argc, char *argv[])
{
int i;
struct hostent *host;
if (argc != 2) {
printf("Usage: %s <addr> \n", argv[0]);
exit(1);
}
host = gethostbyname(argv[1]);
if (!host)
error_handing("gethost...error");
printf("Official name: %s \n", host->h_name);
for (i = 0; host->h_aliases[i]; ++i)
printf("Aliases %d: %s \n", i+1, host->h_aliases[i]);
printf("Address type: %s \n",
(host->h_addrtype == AF_INET) ? "AF_INET" : "AF_INET6");
for (i = 0; host->h_addr_list[i]; ++i)
printf("IP addr %d: %s \n", i+1,
inet_ntoa( *(struct in_addr*)host->h_addr_list[i] ));
return 0;
}
void error_handing(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
运行结果:
$ gcc gethostbyname.c -o gethostbyname
$ ./gethostbyname www.baidu.com
Official name: www.a.shifen.com
Aliases 1: www.baidu.com
Address type: AF_INET
IP addr 1: 14.215.177.39
IP addr 2: 14.215.177.38
若只看hostent结构体的定义,结构体成员h_addr_list指向字符串指针数组(由多个字符串地址构成的数组)。但字符串指针数组中的元素实际指向的是(实际保存的是)in_addr结构体变量地址值而非字符串,如图8-3所示。
给出了h_addr_list结构体的参照关系。正因如此,示例中需要进行类型转换,并调用inet_ntoa函数(该函数我应该也会写,可以看看哦)。
当我们可以利用域名获取IP地址,那么我们是否也可以利用IP地址获取域名呢?当然可以啦,我们利用gethostbyaddr()函数,可以找到我的笔记看看哦。