瀏覽器中輸入URL到界面顯示發生了什麼

一次完整的HTTP事務是怎樣的一個過程?瀏覽器中輸入URL到界面顯示發生了什麼?

  • 1、輸入地址
  • 2、域名解析
  • 3、發起TCP三次握手
  • 4、建立TCP連接後發起HTTP請求
  • 5、服務器響應http請求,瀏覽器得到html代碼
  • 6、瀏覽器解析html代碼,並請求html代碼中的資源(css,js,圖片...)
  • 7、瀏覽器對頁面進行渲染呈現給用戶

1、輸入地址

在瀏覽器中輸入網址的時候,瀏覽器其實已經在智能的匹配url了,他從歷史記錄,書籤等地方,找到已經輸入的字符串可能對應的 url,然後給出智能提示,讓你可以補全url地址。

2、域名解析(DNS解析,查找域名對應的IP地址)

怎麼解析到對應的IP地址?

1、查找瀏覽器自身的DNS緩存(可以使用 chrome://net-internals/#dns 來進行查看)

2、查找操作系統自身的DNS緩存(以Windows系統爲例,可以在命令行下使用 ipconfig /displaydns 來進行查看)

3、查找本地的hosts文件(位於C:\Windows\System32\drivers\etc)

4、瀏覽器會發出一個 DNS請求到本地DNS服務器 (本地DNS服務器一般都是你的網絡接入服務器商提供,比如中國電信,中國移動。)(通過的是UDP協議向DNS的53端口發起請求,這個請求是遞歸的請求,也就是運營商的DNS服務器必須得提供給我們該域名的IP地址)

1)運營商的DNS服務器首先查找自身的緩存

2)運營商的DNS代我們的瀏覽器發起迭代DNS解析請求,它首先是會找根域的DNS的IP地址-》(根DNS服務器沒有記錄具體的域名和IP地址的對應關係,而是告訴本地DNS服務器,你可以到域服務器上去繼續查詢,並給出域服務器的地址)

舉個例子:
首先Chrome瀏覽器會解析 www.baidu.com 這個域名(準確的叫法應該是主機名)對應的IP地址。怎麼解析到對應的IP地址?
1) Chrome瀏覽器會首先搜索瀏覽器自身的DNS緩存(緩存時間比較短,大概只有1分鐘,且只能容納1000條緩存),看自身的緩存中是否有www.baidu.com 對應的條目,而且沒有過期,如果有且沒有過期則解析到此結束。 注:我們怎麼查看Chrome自身的緩存?可以使用 chrome://net-internals/#dns 來進行查看
2) 如果瀏覽器自身的緩存裏面沒有找到對應的條目,那麼Chrome會搜索操作系統自身的DNS緩存,如果找到且沒有過期則停止搜索解析到此結束. 注:怎麼查看操作系統自身的DNS緩存,以Windows系統爲例,可以在命令行下使用 ipconfig /displaydns 來進行查看
3) 如果在Windows系統的DNS緩存也沒有找到,那麼嘗試讀取hosts文件(位於C:\Windows\System32\drivers\etc),看看這裏面有沒有該域名對應的IP地址,如果有則解析成功。
4) 如果在hosts文件中也沒有找到對應的條目,瀏覽器就會發起一個DNS的系統調用,就會向本地配置的首選DNS服務器(一般是電信運營商提供的,也可以使用像Google提供的DNS服務器)發起域名解析請求(通過的是UDP協議向DNS的53端口發起請求,這個請求是遞歸的請求,也就是運營商的DNS服務器必須得提供給我們該域名的IP地址),運營商的DNS服務器首先查找自身的緩存,找到對應的條目,且沒有過期,則解析成功。如果沒有找到對應的條目,則有運營商的DNS代我們的瀏覽器發起迭代DNS解析請求,它首先是會找根域的DNS的IP地址(這個DNS服務器都內置13臺根域的DNS的IP地址),找打根域的DNS地址,就會向其發起請求(請問www.baidu.com這個域名的IP地址是多少啊?),根域發現這是一個頂級域com域的一個域名,於是就告訴運營商的DNS我不知道這個域名的IP地址,但是我知道com域的IP地址,你去找它去,於是運營商的DNS就得到了com域的IP地址,又向com域的IP地址發起了請求(請問www.baidu.com這個域名的IP地址是多少?),com域這臺服務器告訴運營商的DNS我不知道www.baidu.com這個域名的IP地址,但是我知道linux178.com這個域的DNS地址,你去找它去,於是運營商的DNS又向linux178.com這個域名的DNS地址(這個一般就是由域名註冊商提供的,像萬網,新網等)發起請求(請問www.baidu.com這個域名的IP地址是多少?),這個時候linux178.com域的DNS服務器一查,誒,果真在我這裏,於是就把找到的結果發送給運營商的DNS服務器,這個時候運營商的DNS服務器就拿到了www.baidu.com這個域名對應的IP地址,並返回給Windows系統內核,內核又把結果返回給瀏覽器,終於瀏覽器拿到了www.baidu.com對應的IP地址,該進行下一步的動作了。 注:一般情況下是不會進行以下步驟的 如果經過以上的4個步驟,還沒有解析成功,那麼會進行如下步驟
5) 操作系統就會查找NetBIOS name Cache(NetBIOS名稱緩存,就存在客戶端電腦中的),那這個緩存有什麼東西呢?凡是最近一段時間內和我成功通訊的計算機的計算機名和Ip地址,就都會存在這個緩存裏面。什麼情況下該步能解析成功呢?就是該名稱正好是幾分鐘前和我成功通信過,那麼這一步就可以成功解析。
6) 如果第5步也沒有成功,那會查詢WINS 服務器(是NETBIOS名稱和IP地址對應的服務器)
7) 如果第6步也沒有查詢成功,那麼客戶端就要進行廣播查找
8) 如果第7步也沒有成功,那麼客戶端就讀取LMHOSTS文件(和HOSTS文件同一個目錄下,寫法也一樣) 如果第八步還沒有解析成功,那麼就宣告這次解析失敗,那就無法跟目標計算機進行通信。只要這八步中有一步可以解析成功,那就可以成功和目標計算機進行通信。


3、發起TCP的3次握手

拿到域名對應的IP地址之後,User-Agent(一般是指瀏覽器)會以一個隨機端口(1024 < 端口 < 65535)向服務器的WEB程序(常用的有httpd,nginx等)80端口發起TCP的連接請求。這個連接請求(原始的http請求經過TCP/IP4層模型的層層封包)到達服務器端後(這中間通過各種路由設備,局域網內除外),進入到網卡,然後是進入到內核的TCP/IP協議棧(用於識別該連接請求,解封包,一層一層的剝開),還有可能要經過Netfilter防火牆(屬於內核的模塊)的過濾,最終到達WEB程序(本文就以Nginx爲例),最終建立了TCP/IP的連接。

​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請求了。
TCP爲什麼需要三次握手呢?
舉個例子:
假設一個老外在故宮裏面迷路了,看到了小明,於是就有下面的對話:
老外: Excuse me,Can you Speak English?
小明: yes 。
老外: OK,I want ...
在問路之前,老外先問小明是否會說英語,小明回答是的,這時老外才開始問路

兩個計算機通信是靠協議(目前流行的TCP/IP協議)來實現,如果2個計算機使用的協議不一樣,那是不能進行通信的,所以這個3次握手就相當於試探一下對方是否遵循TCP/IP協議,協商完成後就可以進行通信了,當然這樣理解不是那麼準確。
爲什麼HTTP協議要基於TCP來實現?
目前在Internet中所有的傳輸都是通過TCP/IP進行的,HTTP協議作爲TCP/IP模型中應用層的協議也不例外,TCP是一個端到端的可靠的面向連接的協議,所以HTTP基於傳輸層TCP協議不用擔心數據的傳輸的各種問題。

爲什需要三次握手?

《計算機網絡》第四版中講“三次握手”的目的是“爲了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤”

書中的例子是這樣的,“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以後的某個時間纔到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段後,就誤認爲是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接

假設不採用“三次握手”,那麼只要server發出確認,新的連接就建立了。由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以爲新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。採用“三次握手”的辦法可以防止上述現象發生。例如剛纔那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。”。主要目的防止server端一直等待,浪費資源。

4、建立TCP連接後,發起http請求

一個典型的 http request header 一般需要包括請求的方法,例如 GET 或者 POST 等,不常用的還有 PUT 和 DELETE 、HEAD、OPTION以及 TRACE 方法,一般的瀏覽器只能發起 GET 或者 POST 請求。

客戶端向服務器發起http請求的時候,會有一些請求信息,請求信息包含三個部分:

| 請求方法URI協議/版本

| 請求頭(Request Header)

| 請求正文:

5、服務器響應http請求(服務器返回一個http響應)

服務器收到了我們的請求,也處理我們的請求,到這一步,它會把它的處理結果返回,也就是返回一個HTPP響應。

HTTP響應與HTTP請求相似,HTTP響應也由3個部分構成,分別是:

l 狀態行:

l 響應頭(Response Header):由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號":"分隔

l 響應正文:包含着我們需要的一些具體信息,比如cookie,html,image,後端返回的請求數據等等。這裏需要注意,響應正文和響應頭之間有一行空格,表示響應頭的信息到空格爲止

在這裏介紹一下常見其他狀態碼含義:

狀態行:

狀態行由協議版本、數字形式的狀態代碼、及相應的狀態描述,各元素之間以空格分隔。

格式:    HTTP-Version Status-Code Reason-Phrase CRLF

例如:    HTTP/1.1 200 OK \r\n

-- 協議版本:是用http1.0還是其他版本

-- 狀態描述:狀態描述給出了關於狀態代碼的簡短的文字描述。比如狀態代碼爲200時的描述爲 ok

-- 狀態代碼:狀態代碼由三位數字組成,第一個數字定義了響應的類別,且有五種可能取值。如下

1xx:信息性狀態碼,表示服務器已接收了客戶端請求,客戶端可繼續發送請求。

100 Continue

101 Switching Protocols

2xx:成功狀態碼,表示服務器已成功接收到請求並進行處理。200 OK 表示客戶端請求成功

204 No Content 成功,但不返回任何實體的主體部分

206 Partial Content 成功執行了一個範圍(Range)請求

3xx:重定向狀態碼,表示服務器要求客戶端重定向。

301 Moved Permanently 永久性重定向,響應報文的Location首部應該有該資源的新URL

302 Found 臨時性重定向,響應報文的Location首部給出的URL用來臨時定位資源

303 See Other 請求的資源存在着另一個URI,客戶端應使用GET方法定向獲取請求的資源

304 Not Modified 服務器內容沒有更新,可以直接讀取瀏覽器緩存

307 Temporary Redirect 臨時重定向。與302 Found含義一樣。302禁止POST變換爲GET,但實際使用時並不一定,307則更多瀏覽器可能會遵循這一標準,但也依賴於瀏覽器具體實現

4xx:客戶端錯誤狀態碼,表示客戶端的請求有非法內容。

400 Bad Request 表示客戶端請求有語法錯誤,不能被服務器所理解

401 Unauthonzed 表示請求未經授權,該狀態代碼必須與 WWW-Authenticate 報頭域一起使用

403 Forbidden 表示服務器收到請求,但是拒絕提供服務,通常會在響應正文中給出不提供服務的原因

404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL

5xx:服務器錯誤狀態碼,表示服務器未能正常處理客戶端的請求而出現意外錯誤。

500 Internel Server Error 表示服務器發生不可預期的錯誤,導致無法完成客戶端的請求

503 Service Unavailable 表示服務器當前不能夠處理客戶端的請求,在一段時間之後,服務器可能會恢復正常

6、瀏覽器得到html代碼,並請求html代碼中的資源

這裏我們只介紹webkit的渲染過程,下圖對應的就是WebKit渲染的過程,這個過程包括:

解析html以構建dom樹 -> 構建render樹 -> 佈局render樹 -> 繪製render樹

瀏覽器在解析html文件時,會”自上而下“加載,並在加載過程中進行解析渲染。在解析過程中,如果遇到請求外部資源時,如圖片、外鏈的CSS、iconfont等,請求過程是異步的,並不會影響html文檔進行加載。

瀏覽器拿到index.html文件後,就開始解析其中的html代碼,遇到js/css/image等靜態資源時,就向服務器端去請求下載(會使用多線程下載,每個瀏覽器的線程數不一樣),這個時候就用上keep-alive特性了,建立一次HTTP連接,可以請求多個資源,下載資源的順序就是按照代碼裏的順序,但是由於每個資源大小不一樣,而瀏覽器又多線程請求請求資源,顯示的順序並不一定是代碼裏面的順序。
瀏覽器在請求靜態資源時(在未過期的情況下),向服務器端發起一個http請求(詢問自從上一次修改時間到現在有沒有對資源進行修改),如果服務器端返回304狀態碼(告訴瀏覽器服務器端沒有修改),那麼瀏覽器會直接讀取本地的該資源的緩存文件。

7、瀏覽器對頁面進行渲染呈現給用戶

解析過程中,瀏覽器首先會解析HTML文件構建DOM樹,然後解析CSS文件構建渲染樹,等到渲染樹構建完成後,瀏覽器開始佈局渲染樹並將其繪製到屏幕上。這個過程比較複雜,涉及到兩個概念: reflow(迴流)和repain(重繪)。

DOM節點中的各個元素都是以盒模型的形式存在,這些都需要瀏覽器去計算其位置和大小等,這個過程稱爲relow;當盒模型的位置,大小以及其他屬性,如顏色,字體,等確定下來之後,瀏覽器便開始繪製內容,這個過程稱爲repain。

頁面在首次加載時必然會經歷reflow和repain。reflow和repain過程是非常消耗性能的,尤其是在移動設備上,它會破壞用戶體驗,有時會造成頁面卡頓。所以我們應該儘可能少的減少reflow和repain。

當文檔加載過程中遇到js文件,html文檔會掛起渲染(加載解析渲染同步)的線程,不僅要等待文檔中js文件加載完畢,還要等待解析執行完畢,纔可以恢復html文檔的渲染線程。因爲JS有可能會修改DOM,最爲經典的document.write,這意味着,在JS執行完成前,後續所有資源的下載可能是沒有必要的,這是js阻塞後續資源下載的根本原因。所以我明平時的代碼中,js是放在html文檔末尾的。

JS的解析是由瀏覽器中的JS解析引擎完成的,比如谷歌的是V8。JS是單線程運行,也就是說,在同一個時間內只能做一件事,所有的任務都需要排隊,前一個任務結束,後一個任務才能開始。但是又存在某些任務比較耗時,如IO讀寫等,所以需要一種機制可以先執行排在後面的任務,這就是:同步任務(synchronous)和異步任務(asynchronous)。

JS的執行機制就可以看做是一個主線程加上一個任務隊列(task queue)。同步任務就是放在主線程上執行的任務,異步任務是放在任務隊列中的任務。所有的同步任務在主線程上執行,形成一個執行棧;異步任務有了運行結果就會在任務隊列中放置一個事件;腳本運行時先依次運行執行棧,然後會從任務隊列裏提取事件,運行任務隊列中的任務,這個過程是不斷重複的,所以又叫做事件循環(Event loop)。

至此,從輸入url到頁面展示的整個過程。。。

 

參考文章:www.cnblogs.com/xianyulaodi/p/6547807.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章