[網絡] 在瀏覽器輸入URL回車以後發生了什麼

 


一  前言

  打開瀏覽器從輸入網址到網頁呈如今你們面前,背後到底發生了什麼?經歷怎麼樣的一個過程?先給你們來張整體流程圖,具體步驟請看下文分解!前端

  

  從URL輸入到頁面展示

  整體來講分爲如下幾個過程:nginx

  (1)URL 解析web

  (2)DNS 解析:將域名解析成 IP 地址redis

  (3)TCP 鏈接:TCP 三次握手apache

  (4)發送 HTTP 請求編程

  (5)服務器處理請求並響應 HTTP 報文centos

  (6)瀏覽器解析渲染頁面設計模式

  (7)斷開鏈接:TCP 四次揮手瀏覽器

二  URL解析

  URL(Uniform Resource Locator),統一資源定位符,用於定位互聯網上資源,俗稱網址。好比 http://www.w3school.com.cn/html/index.asp,遵照如下的語法規則:

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

  各部分解釋以下:

    scheme - 定義因特網服務的類型。常見的協議有 http、https、ftp、file,其中最多見的類型是 http,而 https 則是進行加密的網絡傳輸。

    host - 定義域主機(http 的默認主機是 www)

    domain - 定義因特網域名,好比 w3school.com.cn

    port - 定義主機上的端口號(http 的默認端口號是 80)

    path - 定義服務器上的路徑(若是省略,則文檔必須位於網站的根目錄中)。

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

  解析流程以下:

    (1)地址解析:

      首先判斷你輸入的是一個合法的 URL 仍是一個待搜索的關鍵詞,而且根據你輸入的內容進行自動完成、字符編碼等操做。

    (2)HSTS

      因爲安全隱患,會使用 HSTS 強制客戶端使用 HTTPS 訪問頁面。

    (3)其餘操做

      瀏覽器還會進行一些額外的操做,好比安全檢查、訪問限制(以前國產瀏覽器限制 996.icu)。

    (4)檢查緩存

      

 

三  DNS域名解析

  在瀏覽器輸入網址後,首先要通過域名解析,由於瀏覽器並不能直接經過域名找到對應的服務器,而是要經過 IP 地址。你們這裏或許會有個疑問----計算機既能夠被賦予 IP 地址,也能夠被賦予主機名和域名。好比 www.hackr.jp。那怎麼不一開始就賦予個 IP 地址?這樣就能夠省去解析麻煩。咱們先來了解下什麼是 IP 地址

1  IP 地址

  IP 地址是指互聯網協議地址,是 IP Address 的縮寫。IP 地址是 IP 協議提供的一種統一的地址格式,它爲互聯網上的每個網絡和每一臺主機分配一個邏輯地址,以此來屏蔽物理地址的差別。IP 地址是一個 32 位的二進制數,好比 127.0.0.1 爲本機 IP。

  域名就至關於 IP 地址喬裝打扮的假裝者,帶着一副面具。它的做用就是便於記憶和溝通的一組服務器的地址。用戶一般使用主機名或域名來訪問對方的計算機,而不是直接經過 IP 地址訪問。由於與 IP 地址的一組純數字相比,用字母配合數字的表示形式來指定計算機名更符合人類的記憶習慣。但要讓計算機去理解名稱,相對而言就變得困難了。由於計算機更擅長處理一長串數字。爲了解決上述的問題,DNS 服務應運而生。

2  什麼是域名解析

  DNS 協議提供經過域名查找 IP 地址,或逆向從 IP 地址反查域名的服務。DNS 是一個網絡服務器,咱們的域名解析簡單來講就是在 DNS 上記錄一條信息記錄

  例如 baidu.com 220.114.23.56(服務器外網IP地址)80(服務器端口號)

3  瀏覽器如何經過域名去查詢 URL 對應的 IP 呢

  基本步驟以下:

   

  1. 瀏覽器緩存

    瀏覽器會先檢查是否在緩存中,沒有則調用系統庫函數進行查詢。瀏覽器會按照必定的頻率緩存 DNS 記錄。

  2. 操做系統緩存

    若是瀏覽器緩存中找不到須要的 DNS 記錄,那就去操做系統中找。操做系統也有本身的 DNS緩存,但在這以前,會向檢查域名是否存在本地的 Hosts 文件裏,沒有則向 DNS 服務器發送查詢請求。

  3. 路由器緩存

    路由器也有本身的緩存。

  4. ISP DNS 緩存

    ISP 是互聯網服務提供商(Internet Service Provider)的簡稱,ISP 有專門的 DNS 服務器應對 DNS 查詢請求。ISP DNS 就是在客戶端電腦上設置的首選 DNS 服務器,它們在大多數狀況下都會有緩存。

  5. 根域名服務器查詢

    ISP 的 DNS 服務器還找不到的話,它就會向根服務器發出請求,進行遞歸查詢(DNS 服務器先問根域名服務器.com 域名服務器的 IP 地址,而後再問.baidu 域名服務器,依次類推)在前面全部步驟沒有緩存的狀況下,本地 DNS 服務器會將請求轉發到互聯網上的根域,下面這個圖很好的詮釋了整個流程:

   

4  小結

  瀏覽器經過向 DNS 服務器發送域名,DNS 服務器查詢到與域名相對應的 IP 地址,而後返回給瀏覽器,瀏覽器再將 IP 地址打在協議上,同時請求參數也會在協議搭載,而後一併發送給對應的服務器。接下來介紹向服務器發送 HTTP 請求階段,HTTP 請求分爲三個部分:TCP 三次握手、http 請求響應信息、關閉 TCP 鏈接。

須要注意的點

  1. 遞歸方式:一路查下去中間不返回,獲得最終結果才返回信息(瀏覽器到本地DNS服務器的過程)

  2. 迭代方式,就是本地DNS服務器到根域名服務器查詢的方式。

  3. 什麼是 DNS 劫持

  4. 前端 dns-prefetch 優化

四  創建鏈接

  在客戶端發送數據以前須要發起 TCP 三次握手創建與服務端的鏈接,用以同步客戶端和服務端的序列號和確認號,並交換 TCP 窗口大小信息。所謂三次握手(Three-way Handshake),是指創建一個TCP鏈接時,須要客戶端和服務器總共發送3個包。

1  TCP三次握手

  

  (1) 第一次握手:創建鏈接時,客戶端A發送SYN包(SYN=1,同時選擇一個初始序列號 seq=x )到服務器B,並進入SYN_SEND狀態,等待服務器B確認。

  (2) 第二次握手:服務器B收到SYN包,必須確認客戶A的SYN=1,同時本身也發送一個SYN包(SYN=1,確認號是ack=x+1,同時也要爲本身初始化一個序列號 seq=y),即SYN+ACK包,此時服務器B進入SYN_RECV狀態。

  (3) 第三次握手:客戶端A收到服務器B的SYN+ACK包,向服務器B發送確認包ACK(ack=y+1,本身的序列號seq=Z),此包發送完畢,客戶端A和服務器B進入ESTABLISHED狀態,完成。

2  SYN攻擊

  在三次握手過程當中,服務器發送 SYN+ACK 以後,收到客戶端的ACK以前的TCP鏈接稱爲半鏈接(half-open connect)。此時服務器處於Syn_RECV狀態。當收到ACK後,服務器轉入ESTABLISHED狀態。

  Syn攻擊就是攻擊客戶端在短期內僞造大量不存在的IP地址,向服務器不斷地發送syn包,服務器回覆確認包,並等待客戶的確認,因爲源地址是不存在的,服務器須要不斷的重發直 至超時,這些僞造的SYN包將長時間佔用未鏈接隊列,正常的SYN請求被丟棄,目標系統運行緩慢,嚴重者引發網絡堵塞甚至系統癱瘓。

  Syn攻擊是一個典型的DDOS攻擊。檢測SYN攻擊很是的方便,當你在服務器上看到大量的半鏈接狀態時,特別是源IP地址是隨機的,基本上能夠判定這是一次SYN攻擊。在Linux下能夠以下命令檢測是否被Syn攻擊

  netstat -n -p TCP | grep SYN_RECV

  通常較新的TCP/IP協議棧都對這一過程進行修正來防範Syn攻擊,修改tcp協議實現。主要方法有SynAttackProtect保護機制、SYN cookies技術、增長最大半鏈接和縮短超時時間等。可是不能徹底防範syn攻擊。

3  爲何不能用兩次握手進行鏈接

  答:3次握手完成兩個重要的功能,既要雙方作好發送數據的準備工做(雙方都知道彼此已準備好),也要容許雙方就初始序列號進行協商,這個序列號在握手過程當中被髮送和確認。  

  若是把三次握手改爲僅須要兩次握手,死鎖是可能發生的。以下圖所示,若是計算機Client和Server之間的通訊,假定Client給Server發送一個鏈接請求分組,Server收到了這個分組,併發送了確認應答分組。按照兩次握手的協定,Server認爲鏈接已經成功地創建了,能夠開始發送數據分組。但是,Client在Server的應答分組在傳輸中被丟失的狀況下,將不知道Server是否已準備好,不知道Server創建什麼樣的序列號,Client甚至懷疑Server是否收到本身的鏈接請求分組。在這種狀況下,Client認爲鏈接還未創建成功,將忽略Server發來的任何數據分組,Client只等待鏈接確認應答分組。而Server在發出的數據分組超時後,重複發送一樣的數據分組。這樣就造成了死鎖

 

  另外三次握手能夠防止已失效的鏈接請求報文段忽然又傳到了Server,於是產生錯誤。假定出現一種異常狀況,即Client發出的第一個鏈接請求報文段並無丟失,而是在某些網絡結 點長時間滯留了,一直延遲到鏈接釋放之後的某個時間纔到達Server,原本這是一個早已失效的報文段。但Server收到此失效的鏈接請求報文段後,就誤認爲是Client又發出一次 新的鏈接請求,因而就向Client發出確認報文段,贊成創建鏈接。假定不採用三次握手,那麼只要Server發出確認,新的鏈接就創建了,這樣一直等待Client發來數據,Server的許多資源就這樣白白浪費了。

五  發送HTTP請求

1  請求報文介紹  

TCP 三次握手結束後,開始發送 HTTP 請求報文
  請求報文由請求行(request line)、請求頭(header)、請求體三個部分組成,以下圖所示

 

1. 請求行包含請求方法、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 版本

2. 請求頭包含請求的附加信息,由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號「:」分隔。

  請求頭部通知服務器有關於客戶端請求的信息。它包含許多有關的客戶端環境和請求正文的有用信息。其中好比:Host,表示主機名,虛擬主機;Connection,HTTP/1.1 增長的,使用 keepalive,即持久鏈接,一個鏈接能夠發多個請求;User-Agent,請求發出者,兼容性以及定製化需求。

3. 請求體,能夠承載多個請求參數的數據,包含回車符、換行符和請求數據,並非全部請求都具備請求數據。

name=tom&password=1234&realName=tomson

  上面代碼,承載着 name、password、realName 三個請求參數。

2  請求流程

  TCP/IP 分爲四層,在發送數據時,每層都要對數據進行封裝: 

   

1.  應用層:發送 HTTP 請求

  在前面的步驟咱們已經獲得服務器的 IP 地址,瀏覽器會開始構造一個 HTTP 報文,其中須要注意的點:

    瀏覽器只能發送 GET、POST 方法,而打開網頁使用的是 GET 方法

2. 傳輸層:TCP 傳輸報文

  傳輸層會發起一條到達服務器的 TCP 鏈接,爲了方便傳輸,會對數據進行分割(以報文段爲單位),並標記編號,方便服務器接受時可以準確地還原報文信息。

  在創建鏈接前,會先進行 TCP 三次握手。

3. 網絡層:IP協議查詢Mac地址

  將數據段打包,並加入源及目標的IP地址,而且負責尋找傳輸路線。判斷目標地址是否與當前地址處於同一網絡中,是的話直接根據 Mac 地址發送,不然使用路由表查找下一跳地址,以及使用 ARP 協議查詢它的 Mac 地址。

4. 鏈路層:以太網協議

  以太網協議

    根據以太網協議將數據分爲以「幀」爲單位的數據包,每一幀分爲兩個部分:

      標頭:數據包的發送者、接受者、數據類型

      數據:數據包具體內容

  Mac 地址

    以太網規定了連入網絡的全部設備都必須具有「網卡」接口,數據包都是從一塊網卡傳遞到另外一塊網卡,網卡的地址就是 Mac 地址。每個 Mac 地址都是獨一無二的,具有了一對一的能力。

  廣播

    發送數據的方法很原始,直接把數據經過 ARP 協議,向本網絡的全部機器發送,接收方根據標頭信息與自身 Mac 地址比較,一致就接受,不然丟棄。

  注意:接收方迴應是單播。

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

   大體流程以下:

  

1.  服務器

  服務器是網絡環境中的高性能計算機,它偵聽網絡上的其餘計算機(客戶機)提交的服務請求,並提供相應的服務,好比網頁服務、文件下載服務、郵件服務、視頻服務。而客戶端主要的功能是瀏覽網頁、看視頻、聽音樂等等,二者大相徑庭。 每臺服務器上都會安裝處理請求的應用——web server。常見的 web server 產品有 apache、nginx、IIS 或 Lighttpd 等。

  web server 擔任管控的角色,對於不一樣用戶發送的請求,會結合配置文件,把不一樣請求委託給服務器上處理相應請求的程序進行處理(例如 CGI 腳本,JSP 腳本,servlets,ASP 腳本,服務器端 JavaScript,或者一些其它的服務器端技術等),而後返回後臺程序處理產生的結果做爲響應。

   
          服務器和客戶端區別.png

2. MVC 後臺處理階段

  後臺開發如今有不少框架,但大部分都仍是按照 MVC 設計模式進行搭建的。MVC 是一個設計模式,將應用程序分紅三個核心部件:模型(model)-- 視圖(view)--控制器(controller),它們各自處理本身的任務,實現輸入、處理和輸出的分離。

  簡而言之,首先瀏覽器發送過來的請求先通過控制器,控制器進行邏輯處理和請求分發,接着會調用模型,這一階段模型會獲取 redis db 以及 MySQL 的數據,獲取數據後將渲染好的頁面,響應信息會以響應報文的形式返回給客戶端,最後瀏覽器經過渲染引擎將網頁呈如今用戶面前。

3. HTTP響應報文

  響應報文由響應行(request line)、響應頭部(header)、響應主體三個部分組成。以下圖所示:

   

  (1) 響應行包含:協議版本,狀態碼,狀態碼描述

    狀態碼規則以下:
      1xx:指示信息--表示請求已接收,繼續處理。

      2xx:成功--表示請求已被成功接收、理解、接受。

      3xx:重定向--要完成請求必須進行更進一步的操做。

      4xx:客戶端錯誤--請求有語法錯誤或請求沒法實現。

      5xx:服務器端錯誤--服務器未能實現合法的請求。

  (2) 響應頭部包含響應報文的附加信息,由 名/值 對組成

  (3) 響應主體包含回車符、換行符和響應返回數據,並非全部響應報文都有響應數據

七  瀏覽器解析渲染頁面

  瀏覽器拿到響應文本 HTML 後,接下來介紹下瀏覽器渲染機制

  

  瀏覽器解析渲染頁面分爲一下五個步驟:

    根據 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」方法,將呈現器的內容顯示在屏幕上。

  重繪:某個元素的背景顏色,文字顏色等,不影響元素周圍或內部佈局的屬性,將只會引發瀏覽器的重繪。

  迴流:某個元素的尺寸發生了變化,則需從新計算渲染樹,從新渲染。

八  斷開鏈接

1  四次揮手

  當數據傳送完畢,須要斷開 tcp 鏈接,此時發起 tcp 四次揮手。TCP的鏈接的拆除須要發送四個包,所以稱爲四次揮手(four-way handshake)。客戶端或服務器都可主動發起揮手動做,在socket編程中,任何一方執行close()操做便可產生揮手操做。

  

  (1)客戶端A發送一個FIN,用來關閉客戶A到服務器B的數據傳送(報文段4)。發起方向被動方發送報文,Fin、Ack、Seq,表示已經沒有數據傳輸了。並進入 FIN_WAIT_1 狀態。(第一次揮手:由瀏覽器發起的,發送給服務器,我請求報文發送完了,你準備關閉吧)

  (2)服務器B收到這個FIN,它發回一個ACK,確認序號爲收到的序號加1(報文段5)。和SYN同樣,一個FIN將佔用一個序號。被動方發送確認報文,Ack、Seq,表示贊成關閉請求。此時主動發起方進入 FIN_WAIT_2 狀態。(第二次揮手:由服務器發起的,告訴瀏覽器,我請求報文接受完了,我準備關閉了,你也準備吧)

  (3)服務器B關閉與客戶端A的鏈接,發送一個FIN給客戶端A(報文段6)。被動方向發起方發送報文段,Fin、Ack、Seq,請求關閉鏈接。並進入 LAST_ACK 狀態。(第三次揮手:由服務器發起,告訴瀏覽器,我響應報文發送完了,你準備關閉吧)

  (4)客戶端A發回ACK報文確認,並將確認序號設置爲收到序號加1(報文段7)。發起方向被動方發送報文段,Ack、Seq。而後進入等待 TIME_WAIT 狀態。被動方收到發起方的報文段之後關閉鏈接。發起方等待必定時間2MSL未收到回覆,則正常關閉。(第四次揮手:由瀏覽器發起,告訴服務器,我響應報文接受完了,我準備關閉了,你也準備吧)

2  爲何鏈接的時候是三次握手,關閉的時候倒是四次握手?

  答:由於當Server端收到Client端的SYN鏈接請求報文後,能夠直接發送SYN+ACK報文。其中ACK報文是用來應答的,SYN報文是用來同步的。可是關閉鏈接時,當Server端收到FIN報文時,極可能並不會當即關閉SOCKET,因此只能先回復一個ACK報文,告訴Client端,"你發的FIN報文我收到了"。

  只有等到我Server端全部的報文都發送完了,我才能發送FIN報文,所以不能一塊兒發送。故須要四步握手。

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

  答:雖然按道理,四個報文都發送完畢,咱們能夠直接進入CLOSE狀態了,可是咱們必須假象網絡是不可靠的,有能夠最後一個ACK丟失。因此TIME_WAIT狀態就是用來重發可能丟失的ACK報文。在Client發送出最後的ACK回覆,但該ACK可能丟失。Server若是沒有收到ACK,將不斷重複發送FIN片斷。

  因此Client不能當即關閉,它必須確認Server接收到了該ACK。Client會在發送出ACK以後進入到TIME_WAIT狀態。Client會設置一個計時器,等待2MSL的時間。若是在該時間內再次收到FIN,那麼Client會重發ACK並再次等待2MSL。所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime)。

  MSL指一個片斷在網絡中最大的存活時間,2MSL就是一個發送和一個回覆所需的最大時間。若是直到2MSL,Client都沒有再次收到FIN,那麼Client推斷ACK已經被成功接收,則結束TCP鏈接。

 

參考

  https://www.cnblogs.com/geoffreyone/p/10021290.html

  https://mp.weixin.qq.com/s/aB6vQ0AmE_bmPZnD_5K59Q

相關文章
相關標籤/搜索