前言
最近在進行前端面試方面的一些準備,看了網上許多相關的文章,發現有一個問題始終繞不開: 在瀏覽器中輸入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