天天看點

從URL輸入到頁面展示發生了什麼

總的來說就是下面幾個過程:

DNS解析:将域名解析成IP位址

TCP連接配接:TCP的三次握手

發送HTTP請求

伺服器處理請求并傳回HTTP封包

浏覽器解析渲染頁面

斷開連接配接:TCP四次揮手

URL到底是啥

URL(Uniform Resource Locator)統一資源定位符,用于定位網際網路上資源,俗稱網絡.遵循以下文法規則:

scheme://host.domain:port/path/filename

scheme:定義網際網路服務的類型,常見的類型有:HTTP HTTPS和GTP。

host:定義域主機(http預設是www)

domain:定義網際網路域名,比如xxx.com.cn

port:定義主機上的端口号(http:預設是80)

path:定義伺服器上的路徑

filename:定義文檔/資源的名稱

1 DNS解析

在浏覽器輸入網址後,首先要經過域名解析,因為浏覽器并不能直接通過域名找到對應的伺服器,而是要通過IP位址,之是以我們用的是域名而不是IP,是因為IP是一段數字,特别不容易記住,而域名其實就是IP的僞裝者。

什麼是域名解析

DNS協定提供通過域名查找IP位址,或者是反向通過IP查找域名的服務。DNS是一個網絡伺服器,我們的域名解析簡單來說就是DNS上記錄一條資訊記錄。

浏覽器如何通過域名去查找URL對應的IP的

最厲害的飛機票

上面有飛機,這裡就不詳細解析。

小結

浏覽器通過DNS伺服器發送域名,DNS伺服器查詢與域名對應的IP位址,然後傳回給浏覽器,浏覽器再将IP位址打在協定上,同時請求參數也會在協定搭載,然後一并發送給對方的伺服器。接下來介紹向伺服器發送HTTP請求階段,HTTP請求分為三個部分:TCP三向交握,http請求資訊,關閉TCP連結

2 TCP三向交握
從URL輸入到頁面展示發生了什麼

1 三次握手的過程如下:

  • 用戶端發送一個帶有SYN=1和Seq=X的資料報到伺服器斷端口(第一次握手是由浏覽器發起,告訴伺服器我要發送請求了)
  • 伺服器傳回了一個帶SYN=1 ACK=X+1,Seq=Y的響應報以示傳達确認資訊(第二次握手,由伺服器發送,告訴浏覽器我準備接受了,你趕緊發送)
  • 用戶端再傳一個帶ACK=Y+1,Seq=Z的資料包,代表"握手結束"(第三次握手,有浏覽器發送,告訴伺服器,我馬上就發了,準備接受吧)

為啥需要三次握手

主要是為了防止已失效的連接配接請求突然又傳送到伺服器上。

所謂"已失效的連結請求封包段"是這樣産生的,考慮一種正常情況:用戶端發出連接配接請求,但因連接配接請求封包丢失而未收到确認,于是用戶端再重傳一次連結請求,後來收到了确認,建立了連接配接。資料傳輸後,就釋放了連接配接。用戶端共發送了兩個連接配接請求封包,其中一個丢失,另一個到達了伺服器,這樣是沒有失效的連接配接請求。

但是如果出現一種異常情況,即用戶端發出的第一個連接配接請求封包文段沒有丢失,而是在某個網絡節點長時間滞留(網差),以緻延誤到連接配接釋放以後的某個時間才到達伺服器,本來這是一個早就已失效的封包段,但伺服器收到失效的連接配接請求封包後,就誤以為用戶端又發出一次新的連接配接請求,于是就向用戶端發出确認封包段,同意建立連接配接,假定不采用封包握手,那麼隻要伺服器發出确認就建立連接配接,新的連接配接就建立了。

由于現在用戶端并沒有發出建立連接配接的請求,是以不會理會伺服器的确認,也不會向伺服器發送資料,但是伺服器确認為新的運輸連接配接已經建立,并一直等待用戶端發來資料,伺服器的很多資源就會被浪費。

3 發送HTTP請求

請求封包有請求行,請求頭,請求體組成

請求行大概長這樣

GET/images/logo.gif HTTP/1.1
           

請求行包含請求方法,URL,協定

請求方法:GET,POST,PUT,DELETE,HEAD,OPTIONS,TRACE,PATCH

請求頭

請求頭包含請求的附加資訊,有關鍵字/值對組成,關鍵字和值用英文冒号":"分隔.

請求頭部通知伺服器關于用戶端請求的資訊,它包含許多有關用戶端環境和請求正文的有用資訊。使用keepalive,保持持久連接配接,一個連接配接可以發送多個請求.等

請求體

可以承載請求參數的資料,包含回車符,換行符和請求資料

4 伺服器處理請求傳回HTTP響應封包

主要講HTTP的響應封包

包含協定版本,狀态碼,狀态碼描述

響應行:協定版本,狀态碼,狀态碼描述

響應頭部:響應封包的附加資訊,有名/值對組成

響應主題包含回車符,換行符,響應傳回資料

4 浏覽器解析渲染頁面

浏覽器渲染頁面一共有五個步驟

  • 根據HTML解析出DOM樹
  • 根據CSS解析生成CSS規則樹
  • 結合DOM樹和CSS規則樹,生成渲染樹
  • 根據渲染樹計算每一個節點的資訊
  • 根據計算好的資訊繪制頁面

1.根據 HTML 解析 DOM 樹

  • 根據 HTML 的内容,将标簽按照結構解析成為 DOM 樹,DOM 樹解析的過程是一個深度優先周遊。即先建構目前節點的所有子節點,再建構下一個兄弟節點。
  • 在讀取 HTML 文檔,建構 DOM 樹的過程中,若遇到 script 标簽,則 DOM 樹的建構會暫停,直至腳本執行完畢。

2.根據 CSS 解析生成 CSS 規則樹

  • 解析 CSS 規則樹時 js 執行将暫停,直至 CSS 規則樹就緒。
  • 浏覽器在 CSS 規則樹生成之前不會進行渲染。

3 結合 DOM 樹和 CSS 規則樹,生成渲染樹

  • DOM 樹和 CSS 規則樹全部準備好了以後,浏覽器才會開始建構渲染樹。
  • 精簡 CSS 并可以加快 CSS 規則樹的建構,進而加快頁面相應速度。

4 根據渲染樹計算每一個節點的資訊(布局)

  • 布局:通過渲染樹中渲染對象的資訊,計算出每一個渲染對象的位置和尺寸
  • 回流:在布局完成後,發現了某個部分發生了變化影響了布局,那就需要倒回去重新渲染。

5 根據計算好的資訊繪制頁面

  • 繪制階段,系統會周遊呈現樹,并調用呈現器的“paint”方法,将呈現器的内容顯示在螢幕上
  • 重繪:某個元素的背景顔色,文字顔色等,不影響元素周圍或内部布局的屬性,将隻會引起浏覽器的重繪。
  • 回流:某個元素的尺寸發生了變化,則需重新計算渲染樹,重新渲染。

5 斷開連結 :TCP四次揮手

從URL輸入到頁面展示發生了什麼
  • 用戶端向伺服器發送封包Fin=1,seq=u表示已經沒有資料傳輸,并進入FIN-WAIT-1(終止等待1)狀态。 (第一次揮手:用戶端發起,發送給浏覽器的)
  • 伺服器發送封包ACK=1 seq=v ack=u+1 表示同意關閉請求,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀态。TCP伺服器通知高層的應用程序,用戶端向伺服器的方向就釋放了,這時候處于半關閉狀态,即用戶端已經沒有資料要發送了,但是伺服器若發送資料,用戶端依然要接受。這個狀态還要持續一段時間,也就是整個CLOSE-WAIT狀态持續的時間。用戶端收到伺服器的确認請求後,此時,用戶端就進入FIN-WAIT-2(終止等待2)狀态,等待伺服器發送連接配接釋放封包(在這之前還需要接受伺服器發送的最後的資料)

    (第二次揮手:有伺服器發起,告訴浏覽器,我請求封包接受完了,我準備關閉,你也準備吧)

  • 伺服器向用戶端發送封包 Fin,ACK等請求關閉連接配接,進入LAST_ACK狀态(最後确認狀态)

    (第三次揮手:由伺服器發起來的,告訴用戶端,我的響應封包發送完了,你準備關閉吧)

  • 用戶端向伺服器發送封包段,然後進入TIME_WAIT狀态,伺服器收到請求後就關閉連接配接,用戶端等待一段時間未收到回複,就正常關閉(第四次揮手:由用戶端發起,告訴伺服器,我響應封包接受完了,我準備關閉,你也關閉吧)

為什麼用戶端在TIME_WAIT狀态必須當代2MSL的時間

1 為了保證用戶端發送的最後一個ACK封包段能夠到達伺服器,這個ACK封包段有可能丢失,因為使處于LAST-ACK狀态的伺服器收不到對方發送的FIN+ACK封包段,伺服器會逾時重傳FIN+ACK這個封包段,而用戶端就能在2MSL時間内收到這個封包,然後重傳,重新啟動2MSL計時器,最後,用戶端和伺服器都正常進入到CLOSED狀态。

如果用戶端沒有等待一段時間,就無法收到伺服器發送的重傳封包,因而不會再次發送去确認封包,那麼伺服器就無法按照正常步驟進入CLOSED狀

2 防止已失效連接配接請求封包段,出現在本連接配接中,用戶端發送完最後一個ACK封包後,再經時間2MSL,就可以是本地連接配接持續的時間内所産生的所有封包都從網絡中消失,這樣就不會在下一個新連接配接中出現失效的連接配接請求封包

為什麼連接配接的時候是三次握手,關閉的時候卻是四次握手?

因為當Server端收到Client端的SYN連接配接請求封包後,可以直接發送SYN+ACK封包。其中ACK封包是用來應答的,SYN封包是用來同步的。但是關閉連接配接時,當Server端收到FIN封包時,很可能并不會立即關閉SOCKET,是以隻能先回複一個ACK封包,告訴Client端,“你發的FIN封包我收到了”。隻有等到我Server端所有的封包都發送完了,我才能發送FIN封包,是以不能一起發送。故需要四步握手。

為什麼不能用兩次握手進行連接配接?

3次握手完成兩個重要的功能,既要雙方做好發送資料的準備工作(雙方都知道彼此已準備好),也要允許雙方就初始序列号進行協商,這個序列号在握手過程中被發送和确認。

現在把三次握手改成僅需要兩次握手,死鎖是可能發生的。作為例子,考慮計算機S和C之間的通信,假定C給S發送一個連接配接請求分組,S收到了這個分組,并發 送了确認應答分組。按照兩次握手的協定,S認為連接配接已經成功地建立了,可以開始發送資料分組。可是,C在S的應答分組在傳輸中被丢失的情況下,将不知道S 是否已準備好,不知道S建立什麼樣的序列号,C甚至懷疑S是否收到自己的連接配接請求分組。在這種情況下,C認為連接配接還未建立成功,将忽略S發來的任何資料分 組,隻等待連接配接确認應答分組。而S在發出的分組逾時後,重複發送同樣的分組。這樣就形成了死鎖。

如果已經建立了連接配接,但是用戶端突然出現故障了怎麼辦?

TCP還設有一個保活計時器,顯然,用戶端如果出現故障,伺服器不能一直等下去,白白浪費資源。伺服器每收到一次用戶端的請求後都會重新複位這個計時器,時間通常是設定為2小時,若兩小時還沒有收到用戶端的任何資料,伺服器就會發送一個探測封包段,以後每隔75分鐘發送一次。若一連發送10個探測封包仍然沒反應,伺服器就認為用戶端出了故障,接着就關閉連接配接。