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文件決定