前言
最近在進行前端面試方面的一些準備,看了網上許多相關的文章,發現有一個問題始終繞不開: 在瀏覽器中輸入URL到整個頁面顯示在使用者面前時這個過程中到底發生了什麼。仔細思考這個問題,發現確實很深,這個過程涉及到的東西很多。這個問題的回答真的能夠很好的考驗一個web工程師的水平,於是特意抽出時間來總結一下。
先給大家來張總體流程圖:
總體來說分為以下幾個過程:
- DNS 解析:將域名解析成 IP 地址
- TCP 連線:TCP 三次握手
- 傳送 HTTP 請求
- 伺服器處理請求並返回 HTTP 報文
- 瀏覽器解析渲染頁面
- 斷開連線:TCP 四次揮手
一、什麼是URL?
URL(Uniform Resource Locator),統一資源定位符,用於定位網際網路上資源,俗稱網址。
scheme: // host.domain:port / path / filename ? abc = 123 # 456789
scheme - 定義因特網服務的型別。常見的協議有 http、https、ftp、file,
其中最常見的型別是 http,而 https 則是進行加密的網路傳輸。
host - 定義域主機(http 的預設主機是 www)
domain - 定義因特網域名,比如 baidu.com
port - 定義主機上的埠號(http 的預設埠號是 80)
path - 定義伺服器上的路徑(如果省略,則文件必須位於網站的根目錄中)。
filename - 定義文件/資源的名稱
query - 即查詢引數
fragment - 即 # 後的hash值,一般用來定位到某個位置
複製程式碼
二、DNS域名解析
在瀏覽器輸入網址後,首先要經過域名解析,因為瀏覽器並不能直接通過域名找到對應的伺服器,而是要通過 IP 地址。
-
IP 地址
IP 地址是指網際網路協議地址,是 IP Address 的縮寫。IP 地址是 IP 協議提供的一種統一的地址格式, 它為網際網路上的每一個網路和每一臺主機分配一個邏輯地址,以此來遮蔽實體地址的差異。
-
什麼是域名解析
DNS 協議提供通過域名查詢 IP 地址,或逆向從 IP 地址反查域名的服務。 DNS 是一個網路伺服器,我們的域名解析簡單來說就是在 DNS 上記錄一條資訊記錄。
-
瀏覽器如何通過域名去查詢 URL 對應的 IP 呢?
DNS域名解析分為遞迴查詢和迭代查詢兩種方式,現一般為迭代查詢。
-
小結
瀏覽器通過向 DNS 伺服器傳送域名,DNS 伺服器查詢到與域名相對應的 IP 地址,然後返回給瀏覽器,瀏覽器再將 IP 地址打在協議上,同時請求引數也會在協議搭載,然後一併傳送給對應的伺服器。接下來介紹向伺服器傳送 HTTP 請求階段,HTTP 請求分為三個部分:TCP 三次握手、http 請求響應資訊、關閉 TCP 連線。
擴充套件:DNS優化
- DNS快取:DNS存在著多級快取,從離瀏覽器的距離排序的話,有以下幾種: 瀏覽器快取,系統快取,路由器快取,IPS伺服器快取,根域名伺服器快取,頂級域名伺服器快取,主域名伺服器快取。
- DNS負載均衡(DNS重定向):DNS負載均衡技術的實現原理是在DNS伺服器中為同一個主機名配置多個IP地址,在應答DNS查詢時,DNS伺服器對每個查詢將以DNS檔案中主機記錄的IP地址按順序返回不同的解析結果,將客戶端的訪問引導到不同的機器上去,使得不同的客戶端訪問不同的伺服器,從而達到負載均衡的目的。
三、TCP三次握手
在客戶端傳送資料之前會發起 TCP 三次握手用以同步客戶端和服務端的序列號和確認號,並交換 TCP 視窗大小資訊。
-
TCP 三次握手的過程如下:
- 客戶端傳送一個帶 SYN=1,Seq=X 的資料包到伺服器埠(第一次握手,由瀏覽器發起,告訴伺服器我要傳送請求了)
- 伺服器發回一個帶 SYN=1, ACK=X+1,Seq=Y的響應包以示傳達確認資訊(第二次握手,由伺服器發起,告訴瀏覽器我準備接受了,你趕緊傳送吧)
- 客戶端再回傳一個帶 ACK=Y+1, Seq=Z 的資料包,代表“握手結束”(第三次握手,由瀏覽器傳送,告訴伺服器,我馬上就發了,準備接受吧)
-
為啥需要三次握手 謝希仁著《計算機網路》中講“三次握手”的目的是“為了防止已失效的連線請求報文段突然又傳送到了服務端,因而產生錯誤”。
四、傳送 HTTP 請求
TCP 三次握手結束後,開始傳送 HTTP 請求報文。 請求報文由請求行(request line)、請求頭(header)、請求體四個部分組成,如下圖所示:
-
請求行包含請求方法、URL、協議版本
- 請求方法包含 8 種:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE。
- URL 即請求地址,由 <協議>://<主機>:<埠>/<路徑>?<引數> 組成
- 協議版本即 http 版本號
POST /chapter17/user.html HTTP/1.1
以上程式碼中“POST”代表請求方法,“/chapter17/user.html”表示URL,“HTTP/1.1”代表協議和協議的版本。現在比較流行的是 Http1.1 版本
-
請求頭包含請求的附加資訊,由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號“:”分隔。
請求頭部通知伺服器有關於客戶端請求的資訊。它包含許多有關的客戶端環境和請求正文的有用資訊。其中比如:Host,表示主機名,虛擬主機;Connection,HTTP/1.1 增加的,使用 keepalive,即持久連線,一個連線可以發多個請求;User-Agent,請求發出者,相容性以及定製化需求。
-
請求體,可以承載多個請求引數的資料,包含回車符、換行符和請求資料,並不是所有請求都具有請求資料。
name=tom&password=1234&realName=tomson
上面程式碼,承載著 name、password、realName 三個請求引數。
五、伺服器處理請求並返回 HTTP 報文
每臺伺服器上都會安裝處理請求的應用——Web server。常見的web server產品有apache、nginx、IIS、Lighttpd等。但大部分都還是按照 MVC 設計模式進行搭建的。
六、瀏覽器解析渲染頁面
為避免篇幅過長,瀏覽器渲染相關內容請參閱: 【瀏覽器】渲染原理探究
七、斷開連線
當資料傳送完畢,需要斷開 tcp 連線,此時發起 tcp 四次揮手。
- 發起方向被動方傳送報文,Fin、Ack、Seq,表示已經沒有資料傳輸了。並進入 FIN_WAIT_1 狀態。(第一次揮手:由瀏覽器發起的,傳送給伺服器,我請求報文傳送完了,你準備關閉吧)
- 被動方傳送報文,Ack、Seq,表示同意關閉請求。此時主機發起方進入 FIN_WAIT_2 狀態。(第二次揮手:由伺服器發起的,告訴瀏覽器,我請求報文接受完了,我準備關閉了,你也準備吧)
- 被動方向發起方傳送報文段,Fin、Ack、Seq,請求關閉連線。並進入 LAST_ACK 狀態。(第三次揮手:由伺服器發起,告訴瀏覽器,我響應報文傳送完了,你準備關閉吧)
- 發起方向被動方傳送報文段,Ack、Seq。然後進入等待 TIME_WAIT 狀態。被動方收到發起方的報文段以後關閉連線。發起方等待一定時間未收到回覆,則正常關閉。(第四次揮手:由瀏覽器發起,告訴伺服器,我響應報文接受完了,我準備關閉了,你也準備吧)
後記: 小夥伴們,如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。如果覺得本文還不錯,記得點個贊哦! 本文首發地址為: Vae's Blog