域名系统
域名系统(Domain Name System,DNS)主要用于主机名字与IP地址之间的映射。
主机名既可以是一个简单得名字,如solaris,也可以是一个全限定域名,如solaris.unpbook.com。
资源记录
DNS中的条目称为资源记录(resource record,RR)
A记录把一个主机名映射成一个32位的IPv4的地址。
AAAA记录把一个主机名映射成一个128位的IPv6地址。
PTR记录把IP地址映射成主机名。
MX记录把一个主机指定作为主机的“邮件交换器(mail exchanger)”。
CNAME代表“cononical name”(规范名字),它的常见用法为常用的服务指派CNAME记录,例如下面名为linux的主机有以下2个CNAME记录
解析器和名字服务器
每个组织机构往往运行一个或多个名字服务器,它们通常是所谓的BIND(Berkeley Internet Name Domain)程序。
本书我们编写的应用程序通过调用成为解析器的函数库中的函数接触DNS服务器,常见的解析器函数是gethostbyname和gethostbyaddr。
下图展示了应用程序、解析器和名字服务器的一个典型关系
gethostbyname函数
查找主机名最基本的函数是gethostbyname。如果调用成功,它就返回一个指向hostent结构的指针。
#inlcude <netdb.h> struct hostent *gethostbyname(const char *hostname); struct hostent { char *h_name; /* official (canonical) 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 */ };
gethostbyname执行的是对A记录的查询。它只能返回IPv4地址
下图展示了hostent结构和它包含的信息
下面给出调用gethostbyname的简单例子
1 #include "unp.h" 2 3 int 4 main(int argc, char **argv) 5 { 6 char *ptr, **pptr; 7 char str[INET_ADDRSTRLEN]; 8 struct hostent *hptr; 9 10 while (--argc > 0) { 11 ptr = *++argv; 12 if ( (hptr = gethostbyname(ptr)) == NULL) { 13 err_msg("gethostbyname error for host: %s: %s", 14 ptr, hstrerror(h_errno)); 15 continue; 16 } 17 printf("official hostname: %s\n", hptr->h_name); 18 19 for (pptr = hptr->h_aliases; *pptr != NULL; pptr++) 20 printf("\talias: %s\n", *pptr); 21 22 switch (hptr->h_addrtype) { 23 case AF_INET: 24 pptr = hptr->h_addr_list; 25 for ( ; *pptr != NULL; pptr++) 26 printf("\taddress: %s\n", 27 Inet_ntop(hptr->h_addrtype, *pptr, str, sizeof(str))); 28 break; 29 30 default: 31 err_ret("unknown address type"); 32 break; 33 } 34 } 35 exit(0); 36 }