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;
}

  结果:

ip地址替换java ip地址用域名替换_ip地址替换java


  上述代码中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;
}

  结果:

ip地址替换java ip地址用域名替换_ip地址替换java_02

BUG:

  对于gethostbyaddr函数,有些IP不知道为什么,解析不出来,需要将IP与对应的域名加入到hosts文件中,详细情况可以看这篇文章。此处我选择了一个可以解析出来的IP来跑的。