TCP/IP网络编程:08域名及网络地址

Posted glory-d

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了TCP/IP网络编程:08域名及网络地址相关的知识,希望对你有一定的参考价值。

本篇文件简要介绍了域名系统及其与IP地址之间的关系。

域名系统

DNS(Domain Name System,域名系统)是对IP地址和域名进行相互转换的系统,其核心是DNS服务器。

什么是域名

提供网络服务的服务器端也是通过IP地址区分的,但由于IP地址形式繁琐,通常使用更为简洁的域名来取代IP地址。使用域名请求服务的另一个优点在于,服务器的域名一般不会轻易改变,但其IP地址可能需要经常变动。

DNS服务器

在浏览器的地址栏中输入百度的网站IP地址183.232.231.172即可浏览百度首页,但我们通常输入的是百度的域名www.baidu.com,这样更为方便。从结果来看,两种方式都可以进入百度的主页,并没有什么其他区别。域名是赋予服务器端的虚拟地址,而非实际地址。因此,需要将域名转换为实际的IP地址才能进行正常通信,DNS服务器就是负责域名和IP地址之间转换的工具。

那么DNS服务器的工作方式是怎样的?通常计算机会有内置的默认DNS服务器,但其不可能知道所有的域名和IP地址信息。若默认DNS服务器无法解析,则会询问其他DNS服务器,并将最终结果反馈给用户。

技术图片

 DNS请求服务

默认DNS服务器收到自己无法解析的请求,会向上级DNS服务器询问。通过逐级向上请求的方式,到达顶级DNS服务器---根DNS服务器时,它知道该向哪个下级DNS服务器询问,并将最终解析出的IP地址信息原路返回并传递至请求主机。DNS便是这样一种层次化管理的分布式数据库系统。

IP地址和域名之间的转换

之所以有IP地址和域名之间转换的需求,是因为实际的程序编写中通常使用的是更为稳定的域名而非IP地址,这就需要再将域名转换为对应的IP地址信息。看似多余的操作,其实是考虑了程序的可靠性而做的保障。

利用域名获取IP地址

#include <netdb.h>

struct hostent *gethostbyname(const char *hostname);
    -> 成功时返回hostent结构体指针,失败时返回NULL指针

//hostent结构体定义
struct hostent
{
    char *h_name;        //official name
    char **h_aliases     //aliase list
    int h_addrtype;      //host address type
    int h_length;        //address lengh
    char **h_addr_list;  //address list
}

技术图片

 hostent结构体变量结构

技术图片

 h_addr_list结构体成员

hostent结构体变量中最重要的或者说我们最关注的成员是h_addr_list,该变量以字符指针数组的形式保存域名对应的IP地址结构(使用char*而非in_addr*是为了兼容性的考虑,其实更为合适的类型是void*,不过当时void*还并未标准化)。之所以会存在多个IP地址,是考虑到大量用户情况下需要利用多个服务器进行负载均衡。gethostbyname函数的示例代码如下。

技术图片
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <unistd.h>
 4 #include <arpa/inet.h>
 5 #include <netdb.h>
 6 void error_handling(char *message);
 7 
 8 int main(int argc, char *argv[])
 9 {
10     int i;
11     struct hostent *host;
12     if(argc!=2) {
13         printf("Usage : %s <addr>
", argv[0]);
14         exit(1);
15     }
16     
17     host=gethostbyname(argv[1]);
18     if(!host)
19         error_handling("gethost... error");
20 
21     printf("Official name: %s 
", host->h_name);
22     
23     for(i=0; host->h_aliases[i]; i++)
24         printf("Aliases %d: %s 
", i+1, host->h_aliases[i]);
25     
26     printf("Address type: %s 
", 
27         (host->h_addrtype==AF_INET)?"AF_INET":"AF_INET6");
28 
29     for(i=0; host->h_addr_list[i]; i++)
30         printf("IP addr %d: %s 
", i+1,
31                     inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
32     return 0;
33 }
34 
35 void error_handling(char *message)
36 {
37     fputs(message, stderr);
38     fputc(
, stderr);
39     exit(1);
40 }
gethostbyname

技术图片

运行结果

若输入我们所熟悉的百度域名,则可得到如下结果:

[root@XXX-Linux exercises]# ./ttt www.baidu.com

Official name: www.a.shifen.com 
Aliases 1: www.baidu.com 
Address type: AF_INET 
IP addr 1: 183.232.231.172 
IP addr 2: 183.232.231.174 

利用IP地址获取域名

#include <netdb.h>

struct hostent *gethostbyaddr(const char *addr, socklen_t len, int family);
    -> 成功时返回hostent结构体变量指针,失败时返回NULL指针

通过输入google的IP地址,gethostbyaddr函数的示例代码如下。

技术图片
 1 #include <stdio.h>
 2 #include <stdlib.h>
 3 #include <string.h>
 4 #include <unistd.h>
 5 #include <arpa/inet.h>
 6 #include <netdb.h>
 7 void error_handling(char *message);
 8 
 9 int main(int argc, char *argv[])
10 {
11     int i;
12     struct hostent *host;
13     struct sockaddr_in addr;
14     if(argc!=2) {
15         printf("Usage : %s <IP>
", argv[0]);
16         exit(1);
17     }
18 
19     memset(&addr, 0, sizeof(addr));
20     addr.sin_addr.s_addr=inet_addr(argv[1]);
21     host=gethostbyaddr((char*)&addr.sin_addr, 4, AF_INET);
22     if(!host)
23         error_handling("gethost... error");
24 
25     printf("Official name: %s 
", host->h_name);
26 
27     for(i=0; host->h_aliases[i]; i++)
28         printf("Aliases %d: %s 
", i+1, host->h_aliases[i]);
29     
30     printf("Address type: %s 
", 
31         (host->h_addrtype==AF_INET)?"AF_INET":"AF_INET6");
32 
33     for(i=0; host->h_addr_list[i]; i++)
34         printf("IP addr %d: %s 
", i+1,
35                     inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));    
36     return 0;
37 }
38 
39 void error_handling(char *message)
40 {
41     fputs(message, stderr);
42     fputc(
, stderr);
43     exit(1);
44 }
gethostbyaddr

技术图片

运行结果

以上是关于TCP/IP网络编程:08域名及网络地址的主要内容,如果未能解决你的问题,请参考以下文章

TCP/IP网络

网络TCP/IP基础(IP地址网络汇总与规划)

DNS域名解析原理 -- 2019-08-09 10:24:18

TCP/IP协议族

TCP/IP协议族

常用网络命令:ping命令的使用