dns工作過程及原理 (linux dns及android dan的實現差異)
前言
本文分析dns工作過程及原理,給一個簡單的dns實現程式碼流程,並針對linux及android
下實現dns的不同,分別分析,供學習dns參考。
一、DNS功能
DNS(Domain Name System,域名系統),dns用於進行域名解析,說白了,就是給出一個
主機名,你給我找出該主機名對應的ip地址。例如:給你www.baidu.com的主機名,你給
我查出對應的ip地址:163.177.151.109。一些主機名還會有別名,如www.baidu.com就
有別名www.a.shifen.com,甚至不止一個別名,或一個別名有2個ip地址。在linux機子
上,執行nslookup(name service lookup)就是進行域名解析。如下面:
~$ nslookup www.baidu.com
Server: 127.0.0.1
Address: 127.0.0.1#53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name: www.a.shifen.com
Address: 163.177.151.109
Name: www.a.shifen.com
Address: 163.177.151.110
二、DNS的原理
上面介紹了dns的功能,那要實現dns的功能,dns需要做什麼工作?主要就3點:1、記錄dns
伺服器的ip地址(請求進行域名解析的地方);2、向dns伺服器請求進行域名解析(dns
實質工作),3、快取已經解析過的主機名與ip地址對應關係(這樣已快取的就不需要再向
dns伺服器請求解析了)。
一個dns的解析過程如下:
1、 應用程式請求一個主機名解析,如:應用程式跟dns說,我需要知道www.baidu.com
的ip地址,你給我查一下;
2、 Dns先在本地快取中查詢,若查到,返回ip地址給應用,流程結束。若沒查到, 進行
下一步;
3、 Dns把需要查詢的主機名打包進dns資料包,然後把dns資料包傳送到dns服務;
4、 DNS伺服器返回查詢的主機名的dns資料包;
5、 Dns解析資料包,把主機名對應的ip地址返回給應用程式;
下圖為網絡卡抓到的dns資料包的收發,請求www.baidu.com的ip地址:
下圖為dns執行流程:
上面是從本機看到的情況,實際上在向DNS伺服器請求時,所請求的DNS伺服器也不一
定知道主機名對應的ip地址,就會向上一級DNS請求,更多資料請自行查詢dns協議。
下面程式碼片段為freescale小系統上的dns處理過程,看起來流程還是比較清晰簡單的:
wiced_result_t dns_client_hostname_lookup( const char* hostname, wiced_ip_address_t* address, uint32_t timeout_ms )
{
/* 省略部分程式碼*/
...
/* Create socket to send packets */
if ( wiced_udp_create_socket( &socket, WICED_ANY_PORT, WICED_STA_INTERFACE ) != WICED_SUCCESS )
{
return WICED_ERROR;
}
while ( ipv4_address_found == WICED_FALSE && remaining_time > 0)
{
/* Send DNS query messages */
for ( a = 0; a < dns_server_address_count; a++ )
{
wiced_ip_address_t host_ipv6_address;
uint16_t available_space;
/* 建立dns資料包 */
if ( wiced_packet_create_udp( &socket, (uint16_t) ( sizeof(dns_message_header_t) + sizeof(dns_question_t) + hostname_length ), &packet, (uint8_t**) &iter.header, &available_space ) != WICED_SUCCESS )
{
goto exit;
}
/* 省略部分程式碼*/
...
/* 傳送dns資料包 */
if ( wiced_udp_send( &socket, &dns_server_address_array[a], DNS_PORT, packet ) != WICED_SUCCESS )
{
wiced_packet_delete( packet );
goto exit;
}
/* 省略部分程式碼*/
...
}
/* Attempt to receive response packets */
while ( ipv4_address_found == WICED_FALSE && remaining_time > 0 )
{
/* 省略部分程式碼*/
...
/* 接收dns資料包 */
if ( wiced_udp_receive( &socket, &packet, remaining_time ) == WICED_SUCCESS )
{
uint16_t data_length;
uint16_t available_data_length;
wiced_bool_t answer_found = WICED_FALSE;
/* Extract the data */
result = wiced_packet_get_data( packet, 0, (uint8_t**) &iter.header, &data_length, &available_data_length );
if ( ( result != WICED_SUCCESS ) || ( data_length < sizeof(dns_message_header_t) ) )
{
goto exit;
}
/* 解析dns資料包,解析出主機名的ip地址 */
/* 省略部分程式碼*/
...
wiced_packet_delete( packet );
}
/* 省略部分程式碼*/
...
}
}
exit:
wiced_udp_delete_socket( &socket );
/* 省略部分程式碼*/
...
if ( ipv4_address_found == WICED_TRUE )
{
*address = resolved_ipv4_address;
return WICED_SUCCESS;
}
/* 省略部分程式碼*/
...
return WICED_ERROR;
}
三、Linux的dns實現
網上搜索Linux dns時,都是一些linux dns怎麼配置的,配置host.conf,
resolv.conf檔案,配置完後,重啟一下network就好了,至於為什麼配置這些檔案,dns
又是在哪裡執行的,都沒有說明。
在Linux上執行nslookup(name service lookup)或ping(ping主機名,如:ping
www.baidu.com)都會執行dns的動作。執行dns時都是呼叫gethostbyname函式,
gethostbyname函式,傳入主機名,dns執行成功後,返回主機名對應的ip地址。
而gethostbyname函式的實現是在c庫中完成的,也就是dns的整個執行過程都是由c庫實
現,c庫中dns實現過程與上一節介紹的流程原理是相同的,只是還多了一些配置檔案用於
設定引數、dns ip地址什麼的,就是前面提到的host.conf,resolv.conf檔案,這就是為什
麼Linux的dns只需要配置host.conf,resolv.conf檔案,不需要再做其它工作的原因,因為
c庫已經替你完成dns的實際工作。在Linux嵌入式系統中,若發現dns不能正常工作,那就
看一下host.conf,resolv.conf等檔案是否配置正確,還有就是dns執行使用的c庫在機子上
有沒有。
想了解c庫怎麼實現dns的,請自行下載c庫原始碼分析:http://www.gnu.org/software/libc/
四、Android的dns實現
Android也是搭建在Linux之上,而在Android下就沒見到host.conf,resolv.conf這
些檔案,但Android的dns也是能正常工作的。這是因為Android重寫了libc庫的dns實現
部分,重寫的dns程式碼在android\bionic\libc\dns目錄。重寫後的dns,請求dns的介面,
有gethostbyname(相容以前的c庫介面)及android_gethostbynamefornet(給
android使用)介面,但根據不同的dns請求發起者,走的流程有點不一樣,其中還涉及到
了netd的處理。Android java層請求dns時,是通過netd進行,netd呼叫
android_gethostbynamefornet介面。而Android下編譯的ping程式是不通過netd而直
接呼叫gethostbyname介面,但最終還是要走到netd,由netd呼叫
android_gethostbynamefornet介面。Android下dns的請求流程如下圖:
gethostbyname_internal中判斷是否為netd呼叫下來的依據是,
getenv(“ANDROID_DNS_MODE”)返回是否不為NULL並且值為“local”,而netd啟動
時會設定setenv(“ANDROID_DNS_MODE”, “local”, 1),而ping程式不會。
五、Linux的dns快取
Linux的dns,在配置resolv.conf檔案的時候,第一個dns ip地址配置為nameserver
127.0.0.1,也就是從本地dns快取中查詢,查詢不到時再根據第二個、第三個dns ip地址
進行dns請求。
六、第三方dns庫
有時候我們不想使用編譯工具中libc自帶的dns庫,也可以移植第三
方的dns庫,如c-ares dns庫,該dns庫支援多種平臺。例如:linux
平臺上,它與linux的配置完全相容,可以在現有的linux dns配置文
件上,直接編譯c-ares庫放到機子上即可使用。
相關推薦
dns工作過程及原理 (linux dns及android dan的實現差異)
前言 本文分析dns工作過程及原理,給一個簡單的dns實現程式碼流程,並針對linux及android 下實現dns的不同,分別分析,供學習dns參考。 一、DNS功能 DNS(Domain Name System,域名系統),dns用於進行域名解
客戶端到伺服器端的通訊過程及原理(很清晰,保證看後頓悟)
學習任何東西,我們只要搞清楚其原理,就會觸類旁通。現在結和我所學,我想總結一下客戶端到伺服器端的通訊過程。只有明白了原理,我們才會明白當我們程式開發過程中錯誤的問題會出現在那,才會更好的解決問題。 我們首先要了解一個概念性的詞彙:Socket sock
kubernetes安裝過程中錯誤(kube-dns 狀態一直是Pending,master節點是NotReady)
安裝環境如下: cenos7系統 kubeadm安裝方法 版本是:kubernetes1.10 K8s安裝完成後,發現所有的pod都起了,除了kube-dns ,顯示的狀態一直是Pending.
solr搜索之入門及原理(一)
solr solr入門 1 solr簡介solr官方文檔:http://wiki.apache.org/solr/DataImportHandler 下載地址:http://www.apache.org/dyn/closer.cgi/lucene/solr/2 solr入門我們使
MQTT協議學習及實踐(Linux服務端,Android客戶端的例子)
nbsp hub 設備 log config cati href 10.10.4 rmi 前言 MQTT(Message Queuing Telemetry Transport),是一個物聯網傳輸協議,它被設計用於輕量級的發布/訂閱式消息傳輸,旨在為低帶寬和不穩定
徹底弄懂HTTP緩存機制及原理(轉載)
一次 chrom https 分開 res 技術 觸發 明顯 總結 https://www.cnblogs.com/chenqf/p/6386163.html 前言 Http 緩存機制作為 web 性能優化的重要手段,對於從事 Web 開發的同學們來說,應該是知識體系庫中的
雜記——controller的工作原理(以CSDN網站導航條為例)
最近初學springMVC,今天明白了controller和jsp之間聯絡的工作原理,於是記一個小筆記。 先看一個程式碼 下面是controller中的一個cookieBind方法 @RequestMapping(value="/cookiebind", method = {Reques
jmeter安裝及使用(linux)
(1)將jmeter安裝包壓縮zip上傳到伺服器/opt/software/apache-jmeter-4.0.zip (2)解壓: unzip apache-jmeter-4.0.zip (3)配置環境變數 3.1) vim /etc/profile 3.2)
Java併發基礎-鎖的使用及原理(可重入鎖、讀寫鎖、內建鎖、訊號量等)
本文目錄: 1 基礎 1.1 可重入鎖 可重入鎖表示的是,如果一個執行緒在未釋放已獲得鎖的情況下再次對該物件加鎖,將可以加鎖成功。而且可以不斷的加鎖成功多次。但需要注意的是,每次加鎖操作必須對應著一次釋放鎖的操作。 如以下示例是可以執行的(
淺析RxJava 1.x&2.x版本使用區別及原理(一):Observable、Flowable等基本元素原始碼解析
RxJava開源框架的風靡程度在Github上無需多言,它帶來的響應式程式設計模式和執行緒隨意切換、巢狀請求、背壓等功能給了開發者耳目一新的體驗,更是成為了大多數APP中常用的RxJava+Okhttp/Retrofit+MVP/MVVM/Clean黃金組合中的
ClassLoader的工作原理(Java中和Andriod中的一些區別)
早期使用過 Eclipse 等 Java 編寫的軟體的同學可能比較熟悉,Eclipse 可以載入許多第三方的外掛(或者叫擴充套件),這就是動態載入。這些外掛大多是一些 Jar 包,而使用外掛其實就是動態載入 Jar 包裡的 Class 進行工作。這其實非常好理解,Ja
編譯器的工作過程和原理
原始碼要執行,必須先轉成二進位制的機器碼。這是編譯器的任務。 比如,下面這段原始碼(假定檔名叫做test.c)。 #include <stdio.h> int main(void) { fputs("Hello, world!\n", stdout);
【 專欄 】- 作業系統原理(linux)
作業系統原理(linux) BIOS(BIOS中斷服務程式),Intel風格x86彙編的核心引導主程式,從真實模式下怎麼進入保護模式,怎麼實現中斷呼叫,怎麼實現特權級檢查,怎麼實現任務的建立,怎麼實現多工的管理;怎麼載入全部核心程
hadoop作業調優引數整理及原理(整個mapreduce執行流程都講的清楚,一步一步優化)
1 Map side tuning引數 1.1 MapTask執行內部原理 當map task開始運算,併產生中間資料時,其產生的中間結果並非直接就簡單的寫入磁碟。這中間的過程比較複雜,並且利用到了記憶體buffer來進行已經產生的部分結果的快取,並在記憶體bu
詳解openstack命令啟動實現流程及原理(nova --debug image-list)
第二個引數就是entry_points.txt檔案group名稱 nova就是傳遞進來的引數,實際指向novaclient.shell模組的main函式 跟進程式碼: 上述程式碼從命令列接收引數,或者從環境變數中獲取引數值,進行驗證等操作。 nova --debug im
jdk下載及安裝(linux)
一:jdk安裝 1.jdk下載地址: jdk1.7 64位官方下載地址 http://www.oracle.com/technetwork/java/javase/downloads/index.html 想要下載最新版本,當前也選擇下載即可: 下載歷史版本:從首
VMware虛擬機器三種聯網方法及原理和Linux 三種網路
一、Brigde——橋接:預設使用VMnet0 1、原理: Bridge 橋"就是一個主機,這個機器擁有兩塊網絡卡,分別處於兩個區域網中,同時在"橋"上,執行著程式,讓區域網A中的所有資料包原封不動的流入B,反之亦然。這樣,區域網A和B就無縫的在鏈路層連線起
python中decorator的用法及原理(一)
0、 概念 什麼叫裝飾器,其實也可以叫做包裝器。即對於一個既有的函式func(args),在呼叫它之前和之後,我們希望都做一些事情,把這個函式包裝起來。 python中的裝飾器分為兩類:函式裝飾器和類裝飾器。 這裡我們先討論函式裝飾器。 1. 不帶引數的decorator
13、基因組的拼接原理(轉載沈夢圓的博客)
學習 jpg 知識 general arch fly 技術分享 重復 prot 最近學習了一下基因組的拼接原理,以下是我的學習筆記和一些思考。基因組的拼接原理是高通量測序技術的基礎知識吧,我個人認為即使不做基 因組拼接工作,也可以學習一下幾個主流拼接軟件的算法和原理。我主要
Nginx系列-2.配置LNMP(Linux、Nginx、MySQL、PHP)架構
Linux Nginx Nginx系列-2.配置LNMP(Linux、Nginx、MySQL、PHP)架構 目錄 - Nginx系列 Nginx系列-1.Linux下安裝Nginx Nginx系列-2.配置LNMP(Linux、Nginx、MySQL、PHP)架構 Nginx系列-3.配置Ngi