DNS服务器
DNS服务器
是对IP地址
与域名
进行相互转换的服务器,比如我们可以在浏览器地址栏中输入222.122.915.5
来访问Naver网站,但是这样是很不方便的,我们日常访问的网站何其之多,不可能每个网站都记这一串数字,此时就可以使用域名,即我们在地址栏输入www.naver.com
同样可以访问Naver网站。
所有的计算机中都记录着默认DNS服务器地址,我们在浏览器地址栏中输入域名后,浏览器会通过默认DNS服务器解析得到该域名对应的IP地址,然后通过IP地址来进入该网站。当然,我们计算机内不可能记录所有域名的IP地址,我们访问一个默认DNS服务器无法解析的域名时,就会询问其他的DNS服务器,将最终得到的IP地址返回给浏览器,来访问对应的网站。
当服务器系统运行时,可能由于各种原因,IP地址发生改变,所以在开发时,我们更多的需要利用域名来指定服务器IP地址,虽然域名也会发生改变,但是概率远低于IP地址。我们通过域名解析获得IP地址,然后将IP地址应用于程序中对应的套接字。
通过域名获取IP地址
我们可以利用以下函数来通过域名获得IP地址:
#include <netdb.h>
struct hostent * gethostbyname(const char *hostname);
hostent结构体定义如下:
struct hostent
{
char *h_name; // 用来保存官方域名
char **h_aliases; // 除官方域名外的其他域名,因为一个IP可以绑定多个域名
int h_addrtype; // 保存有地址组信息,如IPv4为AF_INET
int h_length; // 保存有IP的长度,IPv4为4字节,IPv6为16字节
char **h_addr_list; // 保存有该域名对应的整数形式的IP地址,这是一个列表,其中可能保存有多个IP
}
实操
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netdb.h>
void error_handing(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char *argv[])
{
struct hostent *host;
int i;
host = gethostbyname(argv[1]);
if(!host) error_handing("gethostbyname error");
printf("官方域名:official name:%s \n", host->h_name);
for(i = 0; host->h_aliases[i]; i++) printf("其他域名: %s \n", host->h_aliases[i]);
printf("地址族: %s \n", (host->h_addrtype == AF_INET)?"AF_INET":"AF_INET6");
for(i = 0; host->h_addr_list[i]; i++)
printf("IP%d:%s \n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
return 0;
}
结果:
上述代码中host->h_addr_list[i]
保存的是32位整数型的IP地址,我们要以点分十进制样式的字符串来输出它,就要使用inet_ntoa
函数,而此函数的输入值需要是in_addr结构体
类型,所以我们对其进行了转化。
通过IP地址获取域名
利用以下函数可以通过IP地址获取域名
#include <netdb.h>
struct hostent * gethostbyaddr(const char *addr, socklen_t len, int family);
实操:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#include <netdb.h>
void error_handing(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char *argv[])
{
struct hostent *host;
struct sockaddr_in addr;
int i;
memset(&addr, 0, sizeof(addr));
// addr.sin_addr.s_addr = inet_addr(argv[1]);
inet_aton(argv[1], &addr.sin_addr);
host = gethostbyaddr((char *)&addr.sin_addr, 4, AF_INET);
if(!host) error_handing("gethostbyaddr error");
printf("官方域名:official name:%s \n", host->h_name);
for(i = 0; host->h_aliases[i]; i++) printf("其他域名: %s \n", host->h_aliases[i]);
printf("地址族: %s \n", (host->h_addrtype == AF_INET)?"AF_INET":"AF_INET6");
for(i = 0; host->h_addr_list[i]; i++)
printf("IP%d:%s \n", i+1, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
return 0;
}
结果:
BUG:
对于gethostbyaddr
函数,有些IP不知道为什么,解析不出来,需要将IP
与对应的域名加入到hosts
文件中,详细情况可以看这篇文章。此处我选择了一个可以解析出来的IP来跑的。