getaddrinfo工作原理分析

getaddrinfo工作原理分析

将域名解析成ip地址是所有涉及网络通讯功能程序的基本步骤之一,常用的两个接口是gethostbyname和getaddrinfo,而后者是Posix标准推荐在新应用中使用的接口。很好奇,getaddrinfo的工作原理,接下来就简要分析getaddrinfo函数的工作过程。

函数原型

#include<netdb.h>
int getaddrinfo( const char *hostname, const char *service, const struct addrinfo *hints, struct addrinfo **result );
//返回值:成功 返回 0;错误 返回非零错误码

参数

  • hostname:一个主机名或者地址串(IPv4的点分十进制串或者IPv6的16进制串)
  • service:服务名可以是十进制的端口号,也可以是已定义的服务名称,如ftp、http等
  • hints: hints是一个模板,它只使用ai_family,ai_flags,以及ai_socktype成员,用来过滤地址。剩下的整数成员必须被设置成0.
  • result:本函数通过result指针参数返回一个指向addrinfo结构体链表的指针。
    addrinfo 结构
struct addrinfo {
  int               ai_flags;       /* customize behavior */
  int               ai_family;      /* address family */
  int               ai_socktype;    /* socket type */
  int               ai_protocol;    /* protocol */
  socklen_t         ai_addrlen;     /* length in bytes of address */
  struct sockaddr  *ai_addr;        /* address */
  char             *ai_canonname;   /* canonical name of host */
  struct addrinfo  *ai_next;        /* next in list */
  .
 };

功能分析

Flag Description
AI_ADDRCONFIG 请求配置的是哪种地址类型(IPv4或者IPv6)。
AI_ALL 对IPv4和IPv6地址都进行查找(只和AI_V$MAPPED一块使用)。
AI_CANONNAME 请求一个正式的名称(和别名相对)。
AI_NUMERICHOST 以数字形式返回主机地址。
AI_NUMERICSERV 将服务作为端口号码返回。
AI_PASSIVE 绑定套接字地址以便侦听。
AI_V4MAPPED 如果没有发现IPv6地址,那么返回以IPv6格式映射的IPv4地址。

实例分析过程

要想知道getaddrinfo是如何查询信息的,可以用strace工具,追踪getaddrinfo函数 在执行时打开了哪些文件。
利用APUE 第三版 图16-9的程序,来分析

$ gcc 16-9.c -o getaddr
$ strace -e trace=file -o file ./getaddr google.com http
$ cat file

截取file中与本次目的相关输出

open("/etc/nsswitch.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/services", O_RDONLY|O_CLOEXEC) = 3
open("/etc/host.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/resolv.conf", O_RDONLY|O_CLOEXEC) = 3
open("/etc/hosts", O_RDONLY|O_CLOEXEC) = 3

现在来逐个分析这些文件

/etc/services

该文件是记录网络服务名和它们对应使用的端口号及协议。

/etc/host.conf

该文件指定如何解析主机名,cat /etc/host.conf

# The "order" line is only used by old versions of the C library.
order hosts,bind
multi on

“order hosts,bind”指定主机名查询顺序,这里规定先查询“/etc/hosts”文件,然后再使用DNS来解析域名(也可以相反)。
“multi on”指定是否“/etc/hosts”文件中指定的主机可以有多个地址,拥有多个IP地址的主机一般称为多穴主机。
其中BIND是一种开源的DNS(Domain Name System)协议的实现,包含对域名的查询和响应所需的所有软件。它是互联网上最广泛使用的一种DNS服务器,对于类UNIX系统来说,已经成为事实上的标准。

/etc/hosts

保存主机名和IP配置文件,Linux 的/etc/hosts是配置ip地址和其对应主机名的文件,这里可以记录本机的或其他主机的ip及其对应主机名

/etc/resolv.conf

文件功能:DNS客户机配置文件,设置DNS服务器的IP地址及DNS域名

/etc/nsswitch.conf

文件/etc/nsswitch.conf(name service switch configuration,名字服务切换配置)规定通过哪些途径以及按照什么顺序通过这些途径来查找特定类型的信息。还可以指定若某个方法奏效抑或失效系统将采取什么动作。
cat /etc/nsswitch.conf ,截取 hosts一项
hosts: files mdns4_minimal [NOTFOUND=return] dns mdns4

  • files 表示解析位于 /etc/hosts文件中的静态主机名。
  • mdns4_minimal 试图用组播DNS ( Multicast DNS)来解析名字。
  • [NOTFOUND=return] 意思是mdns4_minimal没有找到就不再继续了.
  • dns 代表传统的单播DNS (unicast DNS)查询 .
  • mdns4 代表一个多播DNS查询

结论(个人看法,如有错误,欢迎指正)

1.读取/etc/nsswitch.conf,若是先读hosts文件,则根据名字在hosts文件中查找,若找到,则返回,若找不到,则使用DNS Bind客户端进行域名解析处理
2.读取/etc/services,查询通用服务名与端口号对应关系。
3.读取/etc/host.conf 该配置文件为域名解析顺序配置文件,设定解析顺序方式
4.读取/etc/resolv.conf配置文件,该文件用于指定解析的DNS服务器,以及DNS Bind解析时的相关参数,如重试次数,超时时间等
5.读取/etc/hosts 文件,查找主机名查询静态表
6.hosts文件未找到主机名时,使用DNS Bind客户端进行域名解析时,会采用/etc/resolv.conf配置文件进行域名解析,解析的方式由resolve.conf文件决定

posted @ 2015-01-20 11:15  battzion  阅读(6857)  评论(0编辑  收藏  举报