[回爐計劃]當輸入xxxxhub的時候,竟然是這樣

前言

回爐計劃第三篇,這是一個經典的前端面試題,考察範圍很是的廣,可深刻的角度也很是的多。本篇文章的目的主要是回顧,因此內容和網絡上流傳的文章會有必定的重疊性。css

過程

過程大體分爲如下幾個步驟html

  1. DNS 解析
  2. TCP 鏈接
  3. 發送 HTTP 請求
  4. 服務器處理請求並返回 HTTP 報文
  5. 瀏覽器解析渲染頁面
  6. 鏈接結束

DNS 解析

DNS 服務和 HTTP 協議同樣,都是位於應用層的協議,它提供域名到 ip 地址之間的解析服務。 以查詢www.baidu.com的 ip 地址爲例前端

  1. 瀏覽器搜索本身的 DNS 緩存(維護一張域名與 IP 地址的對應表)
  2. 搜索操做系統中的 DNS 緩存(維護一張域名與 IP 地址的對應表)
  3. 搜索操做系統的 hosts 文件( Windows 環境下,維護一張域名與 IP 地址的對應表
  4. 操做系統將域名發送至 LDNS(本地區域名服務器,若是你在學校接入互聯網,則 LDNS 服務器就在學校,若是經過電信接入互聯網,則 LDNS 服務器就在你當地的電信那裏。)LDNS 查詢本身的 DNS 緩存(通常查找成功率在 80% 左右),查找成功則返回結果,失敗則發起一個迭代 DNS 解析請求;
    1. LDNS 向 Root Name Server (根域名服務器,其雖然沒有每一個域名的的具體信息,但存儲了負責每一個域,如 com、net、org 等的解析的頂級域名服務器的地址)發起請求,此處,Root Name Server 返回 com 域的頂級域名服務器的地址;
    2. LDNS 向 com 域的頂級域名服務器發起請求,返回 baidu.com 域名服務器地址;
    3. LDNS 向 baidu.com 域名服務器發起請求,獲得 www.baidu.com 的 IP 地址;
  5. LDNS 將獲得的 IP 地址返回給操做系統,同時本身也將 IP 地址緩存起來
  6. 操做系統將 IP 地址返回給瀏覽器,同時本身也將 IP 地址緩存起來
  7. 至此,瀏覽器已經獲得了域名對應的 IP 地址

補充:域名和 url 是兩個概念,域名是用來確認服務器的地址的,而 url 是用來確認資源的地址;域名和 ip 地址不是一一對應的,一個域名同一時刻只能解析出一個 ip 地址,而一個 ip 地址能夠綁定多個域名html5

TCP 鏈接

這就涉及到著名的 http 三次握手。簡單來講與服務器創建鏈接須要經歷如下三個過程。web

  1. 第一次握手:創建鏈接時,客戶端發送 syn 包(syn=j)到服務器,並進入 SYN_SEND 狀態,等待服務器確認;
  2. 第二次握手:服務器收到 syn 包,必須確認客戶的 synack=j+1),同時本身也發送一個 SYN 包(syn=k),即 SYN+ACK 包,此時服務器進入 SYN_RECV 狀態;
  3. 第三次握手:客戶端收到服務器的 SYN+ACK 包,向服務器發送確認包 ACK(ack=k+1),此包發送完畢,客戶端和服務器進入 ESTABLISHED 狀態,完成三次握手。

這裏能夠延申拓展一下 HTTPS 的知識 HTTPS 詳解--segmentfault面試

服務器處理請求並返回 HTTP 報文

這一步主要是後端從接口獲取到 tcp 報文,處理以後返回HTTP Request對象,也就是響應報文。編程

HTTP 響應報文也是由三部分組成: 狀態碼, 響應報頭和響應報文。segmentfault

狀態碼由三位數字組成,表示響應的類型。狀態碼有五大類 1xx,2xx,3xx,4xx,5xx後端

  • 1xx:指示信息–表示請求已接收,繼續處理。
  • 2xx:成功–表示請求已被成功接收、理解、接受。
  • 3xx:重定向–要完成請求必須進行更進一步的操做。
  • 4xx:客戶端錯誤–請求有語法錯誤或請求沒法實現。
  • 5xx:服務器端錯誤–服務器未能實現合法的請求。

HTTP 狀態碼-菜鳥編程瀏覽器

響應報頭 HTTP 請求頭提供了關於請求,響應或者其餘的發送實體的信息。 HTTP 響應頭信息-菜鳥編程

響應報文:就是服務器返回給瀏覽器的文本信息了,包括 html,js,css 等資源

瀏覽器解析渲染頁面

瀏覽器拿到響應報文以後,開始解析報文並呈現網頁。因爲不一樣的瀏覽器引擎實現的方法可能不一致,咱們以webkit內核爲例進行說明。 WebKit 渲染的過程大體分爲四步 瀏覽器的工做原理:新式網絡瀏覽器幕後揭祕

構建 dom 樹 -> 構建 render 樹 -> 佈局 render 樹 -> 繪製 render 樹

呈現引擎將開始解析 HTML 文檔,並將各標記逐個轉化成「內容樹」上的 DOM 節點。同時也會解析外部 CSS 文件以及樣式元素中的樣式數據。HTML 中這些帶有視覺指令的樣式信息將用於建立另外一個樹結構:呈現樹。

呈現樹包含多個帶有視覺屬性(如顏色和尺寸)的矩形。這些矩形的排列順序就是它們將在屏幕上顯示的順序。

呈現樹構建完畢以後,進入「佈局」處理階段,也就是爲每一個節點分配一個應出如今屏幕上的確切座標。下一個階段是繪製 - 呈現引擎會遍歷呈現樹,由用戶界面後端層將每一個節點繪製出來。

須要着重指出的是,這是一個漸進的過程。爲達到更好的用戶體驗,呈現引擎會力求儘快將內容顯示在屏幕上。它沒必要等到整個 HTML 文檔解析完畢以後,就會開始構建呈現樹和設置佈局。在不斷接收和處理來自網絡的其他內容的同時,呈現引擎會將部份內容解析並顯示出來。

上面說到: 瀏覽器是一個邊解析邊渲染的過程。這個過程就涉及到兩個比較重要的概念:重繪(repain)和迴流(reflow)。

當頁面中元素樣式的改變並不影響它在文檔流中的位置時(例如:colorbackground-colorvisibility等),瀏覽器會將新樣式賦予給元素並從新繪製它,這個過程稱爲重繪。

Render Tree中部分或所有元素的尺寸、結構、或某些屬性發生改變時,瀏覽器從新渲染部分或所有文檔的過程稱爲迴流。

會致使迴流的操做

  • 頁面首次渲染
  • 瀏覽器窗口大小發生改變
  • 元素尺寸或位置發生改變
  • 元素內容變化(文字數量或圖片大小等等)
  • 元素字體大小變化
  • 添加或者刪除可見的 DOM 元素
  • 激活 CSS 僞類(例如::hover)
  • 查詢某些屬性或調用某些方法

會致使迴流的屬性和方法

  • clientWidthclientHeightclientTopclientLeft
  • offsetWidthoffsetHeightoffsetTopoffsetLeft
  • scrollWidthscrollHeightscrollTopscrollLeft
  • scrollIntoView()scrollIntoViewIfNeeded()
  • getComputedStyle()
  • getBoundingClientRect()
  • scrollTo()

頁面在首次加載的時候一定會經歷reflowrepainreflowrepain 過程是很是消耗性能的,尤爲是在移動設備上,它會破壞用戶體驗,有時會形成頁面卡頓。因此咱們應該儘量少的減小 reflowrepain

鏈接結束(四次揮手)

TCP 的鏈接的拆除須要發送四個包,所以稱爲四次揮手(Four-way handshake),也叫作改進的三次握手。客戶端或服務器都可主動發起揮手動做,在 socket 編程中,任何一方執行 close() 操做便可產生揮手操做。

  1. 第一次揮手(FIN=1,seq=x)

假設客戶端想要關閉鏈接,客戶端發送一個 FIN 標誌位置爲 1 的包,表示本身已經沒有數據能夠發送了,可是仍然能夠接受數據。

發送完畢後,客戶端進入 FIN_WAIT_1 狀態。

  1. 第二次揮手(ACK=1,ACKnum=x+1)

服務器端確認客戶端的 FIN 包,發送一個確認包,代表本身接受到了客戶端關閉鏈接的請求,但尚未準備好關閉鏈接。

發送完畢後,服務器端進入 CLOSE_WAIT 狀態,客戶端接收到這個確認包以後,進入 FIN_WAIT_2 狀態,等待服務器端關閉鏈接。

  1. 第三次揮手(FIN=1,seq=y)

服務器端準備好關閉鏈接時,向客戶端發送結束鏈接請求,FIN 置爲 1。

發送完畢後,服務器端進入 LAST_ACK 狀態,等待來自客戶端的最後一個 ACK。

  1. 第四次揮手(ACK=1,ACKnum=y+1)

客戶端接收到來自服務器端的關閉請求,發送一個確認包,並進入 TIME_WAIT 狀態,等待可能出現的要求重傳的 ACK 包。

服務器端接收到這個確認包以後,關閉鏈接,進入 CLOSED 狀態。

客戶端等待了某個固定時間(兩個最大段生命週期,2MSL,2 Maximum Segment Lifetime)以後,沒有收到服務器端的 ACK ,認爲服務器端已經正常關閉鏈接,因而本身也關閉鏈接,進入 CLOSED 狀態。

image

【問題 1】爲何鏈接的時候是三次握手,關閉的時候倒是四次握手? 答:由於當 Server 端收到 Client 端的 SYN 鏈接請求報文後,能夠直接發送 SYN+ACK 報文。其中 ACK 報文是用來應答的,SYN 報文是用來同步的。可是關閉鏈接時,當 Server 端收到 FIN 報文時,極可能並不會當即關閉 SOCKET,因此只能先回復一個 ACK 報文,告訴 Client 端,"你發的 FIN 報文我收到了"。只有等到我 Server 端全部的報文都發送完了,我才能發送 FIN 報文,所以不能一塊兒發送。故須要四步握手。

【問題 2】爲何 TIME_WAIT 狀態須要通過 2MSL(最大報文段生存時間)才能返回到 CLOSE 狀態?

答:雖然按道理,四個報文都發送完畢,咱們能夠直接進入 CLOSE 狀態了,可是咱們必須假象網絡是不可靠的,有能夠最後一個 ACK 丟失。因此 TIME_WAIT 狀態就是用來重發可能丟失的 ACK 報文。

參考資料

相關文章
相關標籤/搜索