當我們在瀏覽器的地址欄輸入 www.cnblogs.com ,然后回車,回車到看到頁面到底發生了什么呢?
域名解析 --> 發起TCP的3次握手 --> 建立TCP連接后發起http請求 --> 服務器響應http請求,瀏覽器得到html代碼 --> 瀏覽器解析html代碼,並請求html代碼中的資源(如js、css、圖片等) --> 瀏覽器對頁面進行渲染呈現給用戶
一、域名解析
首先Chrome瀏覽器會解析www.cnblogs.com這個域名對應的IP地址。怎么解析到對應的IP地址?
-
Chrome瀏覽器會首先搜索瀏覽器的DNS緩存(緩存時間比較短,TTL默認是1000,且只能容納1000條緩存),看自身的緩存中是否有www.cnblogs.com對應的條目,而且沒有過期,如果有且沒有過期則解析到此結束。
注:我們怎么查看瀏覽器的DNS緩存?可以使用 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.cnblogs.com這個域名的IP地址是多少啊?),根域發現這是一個頂級域com域的一個域名,於是就告訴運營商的DNS我不知道這個域名的IP地址,但是我知道com域的IP地址,你去找它去,於是運營商的DNS就得到了com域的IP地址,又向com域的IP地址發起了請求(請問www.cnblogs.com這個域名的IP地址是多少?),com域這台服務器告訴運營商的DNS我不知道www.cnblogs.com這個域名的IP地址,但是我知道www.cnblogs.com這個域的DNS地址,你去找它去,於是運營商的DNS又向www.cnblogs.com這個域名的DNS地址(這個一般就是由域名注冊商提供的,像萬網,新網等)發起請求(請問www.cnblogs.com這個域名的IP地址是多少?),這個時候cnblogs.com域的DNS服務器一查,果真在我這里,於是就把找到的結果發送給運營商的DNS服務器,這個時候運營商的DNS服務器就拿到了www.cnblogs.com這個域名對應的IP地址,並返回給Windows系統內核,內核又把結果返回給瀏覽器,終於瀏覽器拿到了www.cnblogs.com對應的IP地址,該進行一步的動作了。
DNS遞歸解析圖如下所示:
DNS迭代解析圖如下所示:
注:一般情況下是不會進行以下步驟的,如果經過以上的4個步驟,還沒有解析成功,那么會進行如下步驟:
-
操作系統就會查找NetBIOS name Cache(NetBIOS名稱緩存,就存在客戶端電腦中的),那這個緩存有什么東西呢?凡是最近一段時間內和我成功通訊的計算機的計算機名和Ip地址,就都會存在這個緩存里面。什么情況下該步能解析成功呢?就是該名稱正好是幾分鍾前和我成功通信過,那么這一步就可以成功解析。
-
如果第5步也沒有成功,那會查詢WINS 服務器(是NETBIOS名稱和IP地址對應的服務器)
-
如果第6步也沒有查詢成功,那么客戶端就要進行廣播查找
-
如果第7步也沒有成功,那么客戶端就讀取LMHOSTS文件(和HOSTS文件同一個目錄下,寫法也一樣)
如果第八步還沒有解析成功,那么這次解析失敗,那就無法跟目標計算機進行通信。只要這八步中有一步可以解析成功,那就可以成功和目標計算機進行通信。
二、發起TCP的3次握手
拿到域名對應的IP地址之后,User-Agent(一般是指瀏覽器)會以一個隨機端口(1024 < 端口 < 65535)向服務器的WEB程序(常用的有tomcat,nginx等)80端口發起TCP的連接請求。這個連接請求(原始的http請求經過TCP/IP4層模型的層層封包)到達服務器端后(這中間通過各種路由設備,局域網內除外),進入到網卡,然后是進入到內核的TCP/IP協議棧(用於識別該連接請求,解封包,一層一層的剝開),還有可能要經過Netfilter防火牆(屬於內核的模塊)的過濾,最終到達WEB程序,最終建立了TCP/IP的連接。如下圖:
三、建立TCP連接后發起http請求
HTTP請求報文的方法是get方式,如果瀏覽器存儲了該域名下的Cookies,那么會把Cookies放入HTTP請求頭里發給服務器。
下面是Chrome發起的http請求報文頭部信息:
GET / HTTP/1.1
Host: www.cnblogs.com
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://www.cnblogs.com/wupeixuan/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
四、服務器端響應http請求,瀏覽器得到html代碼
服務器端WEB程序接收到http請求以后,就開始處理該請求,處理之后就返回給瀏覽器html文件。
用Chrome瀏覽器看到的響應頭信息:
HTTP/1.1 200 OK
Date: Sun, 08 Apr 2018 10:51:00 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Cache-Control: public, max-age=29
Expires: Sun, 08 Apr 2018 10:51:29 GMT
Last-Modified: Sun, 08 Apr 2018 10:50:59 GMT
X-UA-Compatible: IE=10
Content-Encoding: gzip
五、瀏覽器解析html代碼,並請求html代碼中的資源
瀏覽器拿到index.html文件后,就開始解析其中的html代碼,遇到js/css/image等靜態資源時,就向服務器端去請求下載(會使用多線程下載,每個瀏覽器的線程數不一樣),這個時候就用上keep-alive特性了,建立一次HTTP連接,可以請求多個資源,下載資源的順序就是按照代碼里的順序,但是由於每個資源大小不一樣,而瀏覽器又多線程請求請求資源,所以從下圖看出,這里顯示的順序並不一定是代碼里面的順序。
瀏覽器在請求靜態資源時(在未過期的情況下),向服務器端發起一個http請求(詢問自從上一次修改時間到現在有沒有對資源進行修改),如果服務器端返回304狀態碼(告訴瀏覽器服務器端沒有修改),那么瀏覽器會直接讀取本地的該資源的緩存文件。
六、瀏覽器對頁面進行渲染呈現給用戶
最后,Chrome瀏覽器利用自己內部的工作機制,把請求到的靜態資源和html代碼進行渲染,渲染之后呈現給用戶。