【計算機網絡】一個HTTP請求的完整歷程,DNS是怎么解析域名得到IP的?


 最近在排查請求六寸地圖有丟包情況,仔細思考學習了一個請求從客戶端到服務器中間到底經歷了那些環節。記錄一下整個排查過程。

整個流程

域名解析 —> 與服務器建立連接 —> 發起HTTP請求 —> 服務器響應HTTP請求,瀏覽器得到html代碼 —> 瀏覽器解析html代碼,並請求html代碼中的資源(如js、css、圖片) —> 瀏覽器對頁面進行渲染呈現給用戶

 

 

1. 域名解析

以Chrome瀏覽器為例:

① Chrome瀏覽器 會首先搜索瀏覽器自身的DNS緩存(緩存時間比較短,大概只有1分鍾,且只能容納1000條緩存),看自身的緩存中是否有https://www.xxx.com 對應的條目,而且沒有過期,如果有且沒有過期則解析到此結束。

注:我們怎么查看Chrome自身的緩存?可以使用 chrome://net-internals/#dns 來進行查看

② 如果瀏覽器自身的緩存里面沒有找到對應的條目,那么Chrome會搜索操作系統自身的DNS緩存,如果找到且沒有過期則停止搜索解析到此結束.

注:怎么查看操作系統自身的DNS緩存,以Windows系統為例,可以在命令行下使用 ipconfig /displaydns 來進行查看

③ 如果在Windows系統的DNS緩存也沒有找到,那么嘗試讀取hosts文件(位於C:\Windows\System32\drivers\etc),看看這里面有沒有該域名對應的IP地址,如果有則解析成功。

④ 如果在hosts文件中也沒有找到對應的條目,瀏覽器就會發起一個DNS的系統調用,就會向本地配置的首選DNS服務器(一般是電信運營商提供的,也可以使用像Google提供的DNS服務器)發起域名解析請求(通過的是UDP協議向DNS的53端口發起請求,這個請求是遞歸的請求,也就是運營商的DNS服務器必須得提供給我們該域名的IP地址),運營商的DNS服務器首先查找自身的緩存,找到對應的條目,且沒有過期,則解析成功。如果沒有找到對應的條目,則有運營商的DNS代我們的瀏覽器發起迭代DNS解析請求,它首先是會找根域的DNS的IP地址(這個DNS服務器都內置13台根域的DNS的IP地址),找到根域的DNS地址,就會向其發起請求(請問www.xxx.com這個域名的IP地址是多少啊?),根域發現這是一個頂級域com域的一個域名,於是就告訴運營商的DNS我不知道這個域名的IP地址,但是我知道com域的IP地址,你去找它去,於是運營商的DNS就得到了com域的IP地址,又向com域的IP地址發起了請求(請問www.xxx.com這個域名的IP地址是多少?),com域這台服務器告訴運營商的DNS我不知道www.xxx.com這個域名的IP地址,但是我知道xxx.com這個域的DNS地址,你去找它去,於是運營商的DNS又向xxx.com這個域名的DNS地址(這個一般就是由域名注冊商提供的,像萬網,新網等)發起請求(請問www.xxx.com這個域名的IP地址是多少?),這個時候xxx.com域的DNS服務器一查,誒,果真在我這里,於是就把找到的結果發送給運營商的DNS服務器,這個時候運營商的DNS服務器就拿到了www.xxx.com這個域名對應的IP地址,並返回給Windows系統內核,內核又把結果返回給瀏覽器,終於瀏覽器拿到了www.xxx.com 對應的IP地址,該進行一步的動作了。

注:一般情況下是不會進行以下步驟的

如果經過以上的4個步驟,還沒有解析成功,那么會進行如下步驟(以下是針對Windows操作系統):

⑤ 操作系統就會查找NetBIOS name Cache(NetBIOS名稱緩存,就存在客戶端電腦中的),那這個緩存有什么東西呢?凡是最近一段時間內和我成功通訊的計算機的計算機名和Ip地址,就都會存在這個緩存里面。什么情況下該步能解析成功呢?就是該名稱正好是幾分鍾前和我成功通信過,那么這一步就可以成功解析。

⑥ 如果第⑤步也沒有成功,那會查詢WINS 服務器(是NETBIOS名稱和IP地址對應的服務器)

⑦ 如果第⑥步也沒有查詢成功,那么客戶端就要進行廣播查找

⑧ 如果第⑦步也沒有成功,那么客戶端就讀取LMHOSTS文件(和HOSTS文件同一個目錄下,寫法也一樣)

如果第八步還沒有解析成功,那么就宣告這次解析失敗,那就無法跟目標計算機進行通信。只要這八步中有一步可以解析成功,那就可以成功和目標計算機進行通信。

2. 與服務器建立連接

2.1 TCP連接的建立

客戶端的請求到達服務器,首先就是建立TCP連接

來源於:https://blog.csdn.net/u012248450/article/details/51036329

  1. Client首先發送一個連接試探,ACK=0 表示確認號無效,SYN = 1 表示這是一個連接請求或連接接受報文,同時表示這個數據報不能攜帶數據,seq = x 表示Client自己的初始序號(seq = 0 就代表這是第0號包),這時候Client進入syn_sent狀態,表示客戶端等待服務器的回復

  2. Server監聽到連接請求報文后,如同意建立連接,則向Client發送確認。TCP報文首部中的SYN 和 ACK都置1 ,ack = x + 1表示期望收到對方下一個報文段的第一個數據字節序號是x+1,同時表明x為止的所有數據都已正確收到(ack=1其實是ack=0+1,也就是期望客戶端的第1個包),seq = y 表示Server 自己的初始序號(seq=0就代表這是服務器這邊發出的第0號包)。這時服務器進入syn_rcvd,表示服務器已經收到Client的連接請求,等待client的確認。

  3. Client收到確認后還需再次發送確認,同時攜帶要發送給Server的數據。ACK 置1 表示確認號ack= y + 1 有效(代表期望收到服務器的第1個包),Client自己的序號seq= x + 1(表示這就是我的第1個包,相對於第0個包來說的),一旦收到Client的確認之后,這個TCP連接就進入Established狀態,就可以發起http請求了。

問題1:TCP 為什么需要3次握手?

2個計算機通信是靠協議(目前流行的TCP/IP協議)來實現,如果2個計算機使用的協議不一樣,那是不能進行通信的,所以這個3次握手就相當於試探一下對方是否遵循TCP/IP協議,協商完成后就可以進行通信了,當然這樣理解不是那么准確。

問題2:為什么HTTP協議要基於TCP來實現?

目前在Internet中所有的傳輸都是通過TCP/IP進行的,HTTP協議作為TCP/IP模型中應用層的協議也不例外,TCP是一個端到端的可靠的面向連接的協議,所以HTTP基於傳輸層TCP協議不用擔心數據的傳輸的各種問題。

2.2 常見TCP連接限制

2.2.1 修改用戶進程可打開文件數限制

在Linux平台上,無論編寫客戶端程序還是服務端程序,在進行高並發TCP連接處理時,最高的並發數量都要受到系統對用戶單一進程同時可打開文件數量的限制(這是因為系統為每個TCP連接都要創建一個socket句柄,每個socket句柄同時也是一個文件句柄)。可使用ulimit命令查看系統允許當前用戶進程打開的文件數限制,windows上是256,linux是1024,這個博客的服務器是65535

2.2.2 修改網絡內核對TCP連接的有關限制

在Linux上編寫支持高並發TCP連接的客戶端通訊處理程序時,有時會發現盡管已經解除了系統對用戶同時打開文件數的限制,但仍會出現並發TCP連接數增加到一定數量時,再也無法成功建立新的TCP連接的現象。出現這種現在的原因有多種。
第一種原因可能是因為Linux網絡內核對本地端口號范圍有限制。此時,進一步分析為什么無法建立TCP連接,會發現問題出在connect()調用返回失敗,查看系統錯誤提示消息是“Can’t assign requestedaddress”。同時,如果在此時用tcpdump工具監視網絡,會發現根本沒有TCP連接時客戶端發SYN包的網絡流量。這些情況說明問題在於本地Linux系統內核中有限制。

其實,問題的根本原因在於Linux內核的TCP/IP協議實現模塊對系統中所有的客戶端TCP連接對應的本地端口號的范圍進行了限制(例如,內核限制本地端口號的范圍為1024~32768之間)。當系統中某一時刻同時存在太多的TCP客戶端連接時,由於每個TCP客戶端連接都要占用一個唯一的本地端口號(此端口號在系統的本地端口號范圍限制中),如果現有的TCP客戶端連接已將所有的本地端口號占滿,則此時就無法為新的TCP客戶端連接分配一個本地端口號了,因此系統會在這種情況下在connect()調用中返回失敗,並將錯誤提示消息設為“Can’t assignrequested address”。

2.3 TCP四次揮手

當客戶端和服務器通過三次握手建立了TCP連接以后,當數據傳送完畢,肯定是要斷開TCP連接的啊。那對於TCP的斷開連接,這里就有了神秘的“四次分手”。

來源於:https://blog.csdn.net/LRH0211/article/details/72724361

第一次分手:主機1(可以使客戶端,也可以是服務器端),設置Sequence Number,向主機2發送一個FIN報文段;此時,主機1進入FIN_WAIT_1狀態;這表示主機1沒有數據要發送給主機2了;

第二次分手:主機2收到了主機1發送的FIN報文段,向主機1回一個ACK報文段,Acknowledgment Number為Sequence Number加1;主機1進入FIN_WAIT_2狀態;主機2告訴主機1,我“同意”你的關閉請求;

第三次分手:主機2向主機1發送FIN報文段,請求關閉連接,同時主機2進入LAST_ACK狀態;

第四次分手:主機1收到主機2發送的FIN報文段,向主機2發送ACK報文段,然后主機1進入TIME_WAIT狀態;主機2收到主機1的ACK報文段以后,就關閉連接;此時,主機1等待2MSL后依然沒有收到回復,則證明Server端已正常關閉,那好,主機1也可以關閉連接了。

問題:為什么要四次分手?

TCP協議是一種面向連接的、可靠的、基於字節流的運輸層通信協議。TCP是全雙工模式,這就意味着,當主機1發出FIN報文段時,只是表示主機1已經沒有數據要發送了,主機1告訴主機2,它的數據已經全部發送完畢了;但是,這個時候主機1還是可以接受來自主機2的數據;當主機2返回ACK報文段時,表示它已經知道主機1沒有數據發送了,但是主機2還是可以發送數據到主機1的;當主機2也發送了FIN報文段時,這個時候就表示主機2也沒有數據要發送了,就會告訴主機1,我也沒有數據要發送了,之后彼此就會愉快的中斷這次TCP連接。

 

參考文獻

 【計算機網絡】一個完整的HTTP請求過程 https://blog.csdn.net/u013777975/article/details/80496121

一次完整的HTTP請求過程 https://www.cnblogs.com/engeng/articles/5959335.html

后端知識體系–一次完整的HTTP請求 https://blog.csdn.net/u012248450/article/details/51036329

一次完整的HTTP請求與響應涉及了哪些知識? https://blog.csdn.net/LRH0211/article/details/72724361


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM