TCP/IP网络编程 (八):域名及网络地址

域名系统

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

 

什么是域名

提供网络服务的服务器端也是通过IP地址区分的,但几乎不可能以非常难记的IP地址形式交换服务器端地址信息。

 

DNS服务器

在浏览器地址栏中输入Naver网站的IP地址222.122.195.5即可浏览Naver网站主页。但我们通常输入网站的域名www.naver.com访问网站。

 

域名是赋予服务器端的虚拟地址,而非实际地址。因此,需要将虚拟地址转化为实际地址。那如何将域名变为IP地址呢?

DNS服务器担此重任,可以向DNS服务器请求转换地址。所有计算机中都记录着默认DNS服务器地址,就是通过这个默认DNS服务器得到相应域名的IP地址信息。在浏览器地址栏中输入域名后,浏览器通过默认DNS服务器获取该域名对应的IP地址信息,真正接入该网站。

 

ping www.naver.com

这样可知道某一域名对应的IP地址。

先执行命令nslookup,再输入server可以获得计算机中注册的默认DNS服务器地址。

 

 

计算机内置的默认DNS服务器并不知道网络上所有域名的IP地址信息。若该DNS服务器无法解析,则会询问其他DNS服务器,并提供给用户

                                    

 

上图展示了默认DNS服务器无法解析主机询问的域名IP地址时的应答过程:

    默认DNS服务器收到无法解析的请求时,向上级DNS服务器询问,通过这种方式逐级向上传递信息,到达顶级DNS服务器——根DNS服务器时,它知道向哪个DNS服务器访问。向下级DNS服务器传递解析请求,得到IP地址后原路返回,最后将解析的IP地址传递到发起请求的主机。

DNS就是这样层次化管理的一种分布式数据库系统。

 

 

IP地址和域名之间的转换

 

为什么使用域名?

IP地址比域名发生变更的概率要高,所以利用IP地址编写程序并非上策。域名注册后可能永久不变,因此利用域名编写程序会好一些。每次运行程序时根据域名获取IP地址,再接入服务器,这样程序就不会依赖于服务器IP地址了。所以说程序中需要IP地址和域名之间的转换函数。

 

利用域名获取IP地址

使用以下函数可以通过传递字符串格式的域名获取IP地址。

 

此函数传递域名字符串,返回域名对应的IP地址。返回时,地址信息装入hostent结构体。结构体定义如下:

struct hostent
{
    char * h_name;                  //official name
    char ** h_aliases;              //alias list
    int h_addrtype;                 //host address type
    int h_length;                   //address length
    char ** h_addr_list;            //address list
}

域名转换只需关注h_addr_list。

结构体各成员:

h_name: 该变量中存放官方域名。官方域名代表某一主页。

h_aliases: 可以通过多个域名访问 同一主页,同一IP可以绑定多个域名。

h_addrtype: gethostbyname函数不仅支持IPv4,也支持IPv6。通过此变量获取保存在h_addr_list的IP地址的地址族信息。

h_length:保存IP地址的长度。IPv4是4字节,IPv6是16字节。

h_addr_list: 最重要的成员,整数形式保存域名对应的IP地址。用户较多的网站有可能分配多个IP给同一域名,利用多个服务器进行负载均衡。

 

调用gethostbyname函数后返回hostent结构体的变量结构如下图:

                                        

 



/* gethostbyname函数的应用:并说明hostent结构体变量的特性 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>

void error_handling(char *message)
{
	fputs(message,stderr);
	fputc('\n',stderr);
	exit(1);
}

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_handling("gethostbyname() 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++)					//输出IP地址信息
		printf("IP addr %d: %s \n",i+1,inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
	
	return 0;
}

运行结果:


 

 

若只看hostent结构体的定义,结构体成员h_addr_list指向字符串指针数组。但字符串指针数组中的元素实际指向的是in_addr结构体变量地址而非字符串。如图所示:

 

 

利用IP地址获取域名  

 gethostbyaddr函数利用IP地址获取域相关信息。

 

  

/* gethostbyaddr函数的应用 */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<netdb.h>

void error_handling(char *message)
{
	fputs(message,stderr);
	fputc('\n',stderr);
	exit(1);
}

int main(int argc,char *argv[])
{
	int i;
	struct hostent *host;
	struct sockaddr_in addr;

	if (argc != 2)
	{
		printf("Usage: %s <addr> \n",argv[0]);
		exit(1);
	}

	memset(&addr,0,sizeof(addr));
	addr.sin_addr.s_addr = inet_addr(argv[1]);

	host = gethostbyaddr((char*)&addr.sin_addr,4,AF_INET);
	if (!host)
		error_handling("gethostbyaddr() 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++)					//输出IP地址信息
		printf("IP addr %d: %s \n",i+1,inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
	
	return 0;
}


先通过ping获得Google的IP地址,并利用此信息运行示例:

 



完 

猜你喜欢

转载自blog.csdn.net/amoscykl/article/details/80220313
今日推荐