在瀏覽器位址列輸入url到按下回車發生了什麼?

陳堅泓發表於2020-11-29

你越是認真生活,你的生活就會越美好——弗蘭克·勞埃德·萊特
《人生果實》經典語錄

詳解

解析url

瀏覽器通過位址列捕獲到url地址之後,首先對url地址進行解析。url的解析如下圖所示:

在這裡插入圖片描述

一個完整的url,包含上述幾部分,協議部分一般都是 http或者https。域名部分可以是 一段域名例如:baidu.com 也可以是 ip地址,域名最後也會被解析為ip地址。該ip地址的作用就是在網際網路中確定伺服器的位置,緊接著是埠後,埠號確定的是在伺服器中執行的具體的程式。路徑部分表示的是在該程式中資源的具體標識,查詢引數作用主要是為了傳送資料。
URL組成以及hash屬性

DNS解析

一般域名都需要從運營商購買,因為ip地址不方便記憶,域名比較好記。域名都會和ip地址繫結,那麼,在這裡就需要做DNS解析,所謂DNS解析其實就是,根據域名找到其繫結的 ip地址。

查詢的順序如下圖:
在這裡插入圖片描述
DNS的查詢過程解析:

  • 瀏覽器會先檢查是否存在快取,因為如果訪問過一次該域名的話,會把結果快取在瀏覽器中。
  • 作業系統也會有自己的DNS快取,但在這之前,會檢查域名是否存在於本地的Hosts檔案中。
  • 路由器中也會有自己的快取。
  • IPS DNS快取 就是在客戶端電腦上設定的首選DNS伺服器。
  • 在前邊所有的情況下都沒有找到快取的情況下,會連線網際網路,把請求轉發到網際網路的根域。

下圖展示了DNS的一個查詢過程

在這裡插入圖片描述

TCP連線

確定好目標伺服器的ip地址和埠號後,就開始和遠端伺服器建立TCP連結。三次我說的過程如下:

  • 傳送方:傳送訊息,等待…
  • 接收方:接收訊息,並給傳送方回信,此時傳送方接收到訊息後,從傳送方的角度就可明白自己的訊息是可以發過去的。但是接收方還不能確定自己的訊息是否可以正常傳送。
  • 傳送方:接收到傳送方的回信後,在給接收方發一個訊息,此時從接收方的角度就能明白自己的訊息可以可以正常傳送。

畫成圖如下:
在這裡插入圖片描述

TCP三次握手的好處在於的好處在於,傳送方可以確認接收方仍然線上

傳送http請求

http協議是建立在tcp/ip協議之上的,tcp保證連線通暢,http就可以正常的進行請求和響應了。首先http請求是一個無狀態的請求,且只能由瀏覽器主動發起,伺服器進行響應。

瀏覽器傳送請求的報文會攜帶以下資訊

  • 請求路徑
  • 查詢引數
  • 請求方法
  • 請求頭
  • 請求體

伺服器接收請求

在服務端會監聽瀏覽器端傳送的http請求,當瀏覽器的請求發出後,服務端就會接受該請求,並解析出相應的資訊,選擇對應的邏輯進行處理(比如:查詢對應的靜態頁面,儲存檔案,運算元據庫,轉發…),並將處理的結果響應給瀏覽器端。

node伺服器的一個簡單例子如下:

const http = require('http'); // 引入http模組

const server = http.createServer((req, res) => {
	// req儲存了瀏覽器攜帶的資訊
    // 解析出req的相關資訊,比如 路徑 請求方法 請求頭 請求體等
    // 編寫服務端邏輯處理程式碼
    // 響應
    res.end();
})

server.listen(3000, () => console.log('::3000'));

// 假設該程式巡行在 ip地址為 140.143.201.230的伺服器上
// 假設 140.143.201.230 繫結的域名是 www.aabbcc.com
// 那麼請求地址 可以為   http://www.aabbcc.com:3000/home

// 當瀏覽器請求 http://www.aabbcc.com:3000/home之後,會DNS解析到伺服器的ip地址為140.143.201.230,那麼上述http.createServer接收的回撥函式就會執行。

伺服器響應

伺服器執行完邏輯之後,需要給瀏覽器響應內容(無論是要從伺服器獲取資料,還是在伺服器做了什麼操作,都需要給瀏覽器一個響應)

響應一般包含以下幾部分

  • 狀態碼
  • 狀態文字
  • 響應頭
  • 響應體

伺服器響應的同時肯定會伴隨著瀏覽器端接收,等瀏覽器端徹底接收完畢之後,TCP就要進行4次揮手,並斷開連線了。

TCP連結斷開

TCP連結的斷開需要經過"四次揮手",那麼就需要一方主動的釋放另外一方被動的釋放。大體的過程如下:

  1. 瀏覽器端發訊息通知伺服器現在需要斷開(第一次揮手)
  2. 伺服器接到要斷開的請求之後,給瀏覽器返回訊息,告訴瀏覽器我正在準備釋放(第二次揮手)
  3. 此時瀏覽器接到訊息後正在等待伺服器釋放完成,而伺服器正在準備釋放的過程
  4. 當伺服器釋放完成後,再通知瀏覽器我已經釋放完成了。(第三次揮手)
  5. 瀏覽器接收到伺服器釋放完成的訊息後,再給伺服器傳送訊息告訴伺服器我已經知道你釋放完成了,伺服器收到訊息後,就能確認自己釋放完成的訊息已經通知到了(第四次揮手)
    在這裡插入圖片描述

瀏覽器解析資源

當瀏覽器接收到伺服器響應的資源後,會對資源進行解析。

  1. 首先,檢視Response Header,根據響應頭的指示做不同的事情,比如重定向,儲存cookie,解壓gzip,快取資源等等。
  2. 接下來獲取MIME型別(檢視響應頭的 Content-Type的值),根據不同的資源型別採用不同的解析方式

渲染頁面

一般來說從位址列輸入地址後,絕大多是情況下響應的都是 html檔案,那麼就說以說頁面是如何渲染html頁面的,html頁面中一般也會嵌入css,js,圖片等資源。因此如果解析到這些資源的時候,會再次向目標伺服器發起請求,那麼又會經歷從解析url地址開始的各個步驟。

整個頁面的載入如下圖所示:
在這裡插入圖片描述

html頁面的載入

首先要知道瀏覽器解析是從上往下一行一行地解析的。

  1. 解碼:傳輸回來的其實都是一些二進位制位元組資料,瀏覽器需要根據檔案指定編碼(例如UTF-8)轉換成字串,也就是HTML 程式碼
  2. 預解析:預解析做的事情是提前載入資源,減少處理時間,它會識別一些會請求資源的屬性,比如img標籤的src屬性,並將這個請求加到請求佇列中。
  3. 符號化:符號化是詞法分析的過程,將輸入解析成符號,HTML 符號包括,開始標籤、結束標籤、屬性名和屬性值。它通過一個狀態機去識別符號的狀態,比如遇到<,>狀態都會產生變化。
  4. 構建樹:在上一步符號化中,解析器獲得這些標記,然後以合適的方法建立DOM物件並把這些符號插入到DOM物件中。

瀏覽器的容錯機制:你從來沒有在瀏覽器看過類似”語法無效”的錯誤,這是因為瀏覽器去糾正錯誤的語法,然後繼續工作。

css解析

一旦瀏覽器下載了 CSS,CSS 解析器就會處理它遇到的任何 CSS,根據語法規範解析出所有的 CSS 並進行標記化,然後我們得到一個規則表。
在匹配一個節點對應的 CSS 規則時,是按照從右到左的順序的,例如:div p { font-size :14px }會先尋找所有的p標籤然後判斷它的父元素是否為div

所以我們寫 CSS 時,儘量用 id 和 class,千萬不要過度層疊。

javaScript編譯執行

大致流程如下:
在這裡插入圖片描述
主要是三個階段

  1. 詞法分析:js指令碼載入完畢後,會首先進入語法分析階段,它首先會分析程式碼塊的語法是否正確,不正確則丟擲“語法錯誤”,停止執行。
  2. 預編譯:js有三種執行環境分別是 全域性環境,函式環境,eval。每進入一個不同的執行環境都會建立一個對應的執行上下文,根據不同的上下文環境,形成一個函式呼叫棧,棧底永遠是全域性執行上下文,棧頂則永遠是當前執行上下文。
  3. 執行: js雖然是單執行緒的,但是實際參與工作的執行緒一共有四個:JS引擎執行緒(主),事件觸發執行緒,定時器觸發執行緒,HTTP非同步請求執行緒

總結

從瀏覽地位址列輸入地址按下回車,可以看做是一次請求的發起,那麼必然會經歷以下幾個步驟:

  1. 解析url地址
  2. DNS解析
  3. TCP連結
  4. 傳送http請求
  5. 伺服器接收請求
  6. 伺服器響應
  7. TCP連結斷開
  8. 瀏覽器解析資源

那麼我們需要明白,瀏覽器可以傳送請求的方式不止位址列輸入地址這一種。比如a標籤,img,link,script,form表單,ajax,fetch等等,這些方式都可以發出http請求,那麼他們都會經歷上述的過程,最終拿到資源,只是拿到資源的型別不一樣,那麼瀏覽器的處理方式也不一樣。


謝謝你閱讀到了最後~
期待你關注、收藏、評論、點贊~
讓我們一起變得更強

原文連結
在瀏覽器位址列輸入url到按下回車發生了什麼?

推薦閱讀
硬核!30 張圖解 HTTP 常見的面試題
15 張精美動圖全面講解 CORS(跨域資源共享、同源策略)
Vue原始碼學習(持續更新中)

相關文章