域名系统(Domain Name System, DNS)主要用于主机名和IP地址之间的映射,
是一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。
主机名既可是一个简单名字(如solaris),也可是一个全限定域名FQDN(如solaris.unpbook.com)。
每个组织机构往往运行一个或多个名字服务器(name server),客户和服务器等应用程序通过调用解析器(resolver)函数库中的函数接触DNS服务器。
常见的解析函数gethostbyname()和gethostbyaddr(),前者把主机名映射成IPv4地址,后者执行相反映射。
解析器代码通常包含在一个系统函数库中,在构造应用程序时被链编(link-editing)到应用程序中。
另有些系统提供一个由全体应用进程共享的集中式解析器守护进程,并提供向这个守护进程执行RPC的系统函数库代码。
不论哪种情况,应用程序代码使用通常的函数调用来执行解析器中的代码。
解析器代码通过读取其系统相关配置文件确定本组织机构的名字服务器们的所在位置。
文件/etc/resolv.conf通常包含本地名字服务器主机的IP地址。
解析器是UDP向本地名字服务器发出查询。
若本地名字服务器不知道答案,它通常就使用UDP在整个Internet上查询其他名字服务器;
若答案太长,超出了UDP消息的承载能力,本地名字服务器和解析器会自动切换到TCP。
不使用DNS也可能获取名字和地址信息。
常用的方法有静态主机(通常是/etc/hosts文件)、网络信息系统NIS以及轻权目录访问协议LDAP。
#include <netdb.h>
struct hostent *gethostbyname(const char *hostname); // 执行的是对A记录的查询,只能返回IPv4地址。
gethostbyname()是查找主机名最基本的函数,返回对应于给定主机名的包含主机名字和地址信息的hostent结构指针。
出错则为NULL,且设置h_errno(HOST_NOT_FOUND、TRY_AGAIN、NO_RECOVERY、NO_DATA)。
struct hostent
{
char *h_name;
char **h_aliases;
short h_addrtype;
short h_length;
char **h_addr_list;
};
假设查询的主机名有两个别名和3个IPv4地址,在这些字段中所查询的主机的正式主机名和所有别名都是以空字符结尾的C字符串。
#include <netdb.h>
struct hostent *gethostbyaddr(const char *addr, socklen_t len, int family); // 成功则为非空指针,出错则为NULL且设置h_errno。
addr参数实际不是char *类型,而是一个指向存放IPv4地址的某个in_addr结构的指针;
len参数是这个结构的大小,对于IPv4来说为4;
family参数为AF_INET。
gethostbyaddr在in_addr.arpa域中向一个名字服务器查询PTR记录。