前端知識點總結(一):從輸入URL到頁面展示的詳細過程

 

這裏只是簡單地概括一下大致流程:

  • 輸入網址
  • DNS解析
  • 建立tcp連接
  • 客戶端發送HTPP請求
  • 服務器處理請求 
  • 服務器響應請求
  • 瀏覽器展示HTML
  • 瀏覽器發送請求獲取其他在HTML中的資源。

1、輸入地址

  • 當我們開始在瀏覽器中輸入網址的時候,瀏覽器其實就已經在智能的匹配可能得 url 了,他會從歷史記錄,書籤等地方,找到已經輸入的字符串可能對應的 url,然後給出智能提示,讓你可以補全url地址。

2、瀏覽器查找域名的 IP 地址  

  • 請求一旦發起,瀏覽器首先要做的事情就是解析這個域名,一般來說,瀏覽器會首先查看本地硬盤的 hosts 文件,看看其中有沒有和這個域名對應的規則,如果有的話就直接使用 hosts 文件裏面的 ip 地址。
  • 如果在本地的 hosts 文件沒有能夠找到對應的 ip 地址,瀏覽器會發出一個 DNS請求到本地DNS服務器 。本地DNS服務器一般都是你的網絡接入服務器商提供,比如中國電信,中國移動。
  • 查詢你輸入的網址的DNS請求到達本地DNS服務器之後,本地DNS服務器會首先查詢它的緩存記錄,如果緩存中有此條記錄,就可以直接返回結果,此過程是遞歸的方式進行查詢。如果沒有,本地DNS服務器還要向DNS根服務器進行查詢。
  • 根DNS服務器沒有記錄具體的域名和IP地址的對應關係,而是告訴本地DNS服務器,你可以到域服務器上去繼續查詢,並給出域服務器的地址。這種過程是迭代的過程。
  • 本地DNS服務器繼續向域服務器發出請求,在這個例子中,請求的對象是.com域服務器。.com域服務器收到請求之後,也不會直接返回域名和IP地址的對應關係,而是告訴本地DNS服務器,你的域名的解析服務器的地址。
  • 最後,本地DNS服務器向域名的解析服務器發出請求,這時就能收到一個域名和IP地址對應關係,本地DNS服務器不僅要把IP地址返回給用戶電腦,還要把這個對應關係保存在緩存中,以備下次別的用戶查詢時,可以直接返回結果,加快網絡訪問。

 

擴展

1)什麼是DNS?

  DNS(Domain Name System,域名系統),因特網上作爲域名和IP地址相互映射的一個分佈式數據庫,能夠使用戶更方便的訪問互聯網,而不用去記住能夠被機器直接讀取的IP數串。通過主機名,最終得到該主機名對應的IP地址的過程叫做域名解析(或主機名解析)。

2)DNS查詢的兩種方式:遞歸查詢和迭代查詢

1、遞歸解析

    當局部DNS服務器自己不能回答客戶機的DNS查詢時,它就需要向其他DNS服務器進行查詢。此時有兩種方式。局部DNS服務器自己負責向其他DNS服務器進行查詢,一般是先向該域名的根域服務器查詢,再由根域名服務器一級級向下查詢。最後得到的查詢結果返回給局部DNS服務器,再由局部DNS服務器返回給客戶端。

2、迭代解析

  當局部DNS服務器自己不能回答客戶機的DNS查詢時,也可以通過迭代查詢的方式進行解析。局部DNS服務器不是自己向其他DNS服務器進行查詢,而是把能解析該域名的其他DNS服務器的IP地址返回給客戶端DNS程序,客戶端DNS程序再繼續向這些DNS服務器進行查詢,直到得到查詢結果爲止。也就是說,迭代解析只是幫你找到相關的服務器而已,而不會幫你去查。

 

3)DNS域名稱空間的組織方式

 我們在前面有說到根DNS服務器,域DNS服務器,這些都是DNS域名稱空間的組織方式。按其功能命名空間中用來描述 DNS 域名稱的五個類別的介紹詳見下表中,以及與每個名稱類型的示例

 

4)DNS負載均衡

  當一個網站有足夠多的用戶的時候,假如每次請求的資源都位於同一臺機器上面,那麼這臺機器隨時可能會蹦掉。處理辦法就是用DNS負載均衡技術,它的原理是在DNS服務器中爲同一個主機名配置多個IP地址,在應答DNS查詢時,DNS服務器對每個查詢將以DNS文件中主機記錄的IP地址按順序返回不同的解析結果,將客戶端的訪問引導到不同的機器上去,使得不同的客戶端訪問不同的服務器,從而達到負載均衡的目的。例如可以根據每臺機器的負載量,該機器離用戶地理位置的距離等等。

3、瀏覽器向 web 服務器發送一個 HTTP 請求

  拿到域名對應的IP地址之後,瀏覽器會以一個隨機端口(1024<端口<65535)向服務器的WEB程序80端口發起TCP的連接請求這個連接請求到達服務器端後,進入到網卡,然後是進入到內核的TCP/IP協議棧,還有可能要經過Netfilter防火牆的過濾,最終到達WEB程序,最終建立了TCP/IP的連接。

  建立了TCP連接之後,發起一個http請求。一個典型的 http request header 一般需要包括請求的方法,例如 GET 或者 POST 等,不常用的還有 PUT 和 DELETE 、HEAD、OPTION以及 TRACE 方法,一般的瀏覽器只能發起 GET 或者 POST 請求。

  客戶端向服務器發起http請求的時候,會有一些請求信息,請求信息包含三個部分:

  • 請求方法URI協議/版本
  • 請求頭(Request Header)
  • 請求正文:

 

 注意:最後一個請求頭之後是一個空行,發送回車符和換行符,通知服務器以下不再有請求頭。

(1)請求的第一行是“方法URL議/版本”:GET/sample.jsp HTTP/1.1
(2)請求頭(Request Header)
   請求頭包含許多有關的客戶端環境和請求正文的有用信息

(3)請求正文
    請求頭和請求正文之間是一個空行,這個行非常重要,它表示請求頭已經結束,接下來的是請求正文。請求正文中可以包含客戶提交的查詢字符串信息

擴展

1)TCP三次握手

第一次握手:客戶端A將標誌位SYN置爲1,隨機產生一個值爲seq=J(J的取值範圍爲=1234567)的數據包到服務器,客戶端A進入SYN_SENT狀態,等待服務端B確認;

第二次握手:服務端B收到數據包後由標誌位SYN=1知道客戶端A請求建立連接,服務端B將標誌位SYN和ACK都置爲1,ack=J+1,隨機產生一個值seq=K,並將該數據包發送給客戶端A以確認連接請求,服務端B進入SYN_RCVD狀態。

第三次握手:客戶端A收到確認後,檢查ack是否爲J+1,ACK是否爲1,如果正確則將標誌位ACK置爲1,ack=K+1,並將該數據包發送給服務端B,服務端B檢查ack是否爲K+1,ACK是否爲1,如果正確則連接建立成功,客戶端A和服務端B進入ESTABLISHED狀態,完成三次握手,隨後客戶端A與服務端B之間可以開始傳輸數據了。

2)爲什需要三次握手?

  《計算機網絡》第四版中講“三次握手”的目的是“爲了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤”

主要目的防止server端一直等待,浪費資源。

 

3)TCP四次揮手

第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。
第二次揮手:Server收到FIN後,發送一個ACK給Client,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態。
第三次揮手:Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。
第四次揮手:Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手。

 

4)爲什麼建立連接是三次握手,而關閉連接卻是四次揮手呢?

  這是因爲服務端在LISTEN狀態下,收到建立連接請求的SYN報文後,把ACK和SYN放在一個報文裏發送給客戶端。而關閉連接時,當收到對方的FIN報文時,僅僅表示對方不再發送數據了但是還能接收數據,己方也未必全部數據都發送給對方了,所以己方可以立即close,也可以發送一些數據給對方後,再發送FIN報文給對方來表示同意現在關閉連接,因此,己方ACK和FIN一般都會分開發送。

4、服務器的永久重定向響應

 而搜索引擎知道301永久重定向是什麼意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網站排名下。還有就是用不同的地址會造成緩存友好性變差,當一個頁面有好幾個名字時,它可能會在緩存裏出現好幾次。

擴展

1)301和302的區別。

  • 301和302狀態碼都表示重定向,就是說瀏覽器在拿到服務器返回的這個狀態碼後會自動跳轉到一個新的URL地址,這個地址可以從響應的Location首部中獲取(用戶看到的效果就是他輸入的地址A瞬間變成了另一個地址B)——這是它們的共同點。
  • 他們的不同在於。301表示舊地址A的資源已經被永久地移除了,搜索引擎在抓取新內容的同時也將舊的網址交換爲重定向之後的網址;
  • 302表示舊地址A的資源還在,這個重定向只是臨時地從舊地址A跳轉到地址B,搜索引擎會抓取新的內容而保存舊的網址。 

2)重定向原因:

  • 網站調整
  • 網頁被移到一個新地址
  • 網頁擴展名改變

3)什麼時候進行301或者302跳轉呢?

        當一個網站或者網頁24—48小時內臨時移動到一個新的位置,這時候就要進行302跳轉,而使用301跳轉的場景就是之前的網站因爲某種原因需要移除掉,然後要到新的地址訪問,是永久性的。

5、瀏覽器跟蹤重定向地址

6、服務器處理請求

  • 經過前面的重重步驟,我們終於將我們的http請求發送到了服務器這裏,其實前面的重定向已經是到達服務器了,那麼,服務器是如何處理我們的請求的呢?
  • 後端從在固定的端口接收到TCP報文開始,它會對TCP連接進行處理,對HTTP協議進行解析,並按照報文格式進一步封裝成HTTP Request對象,供上層使用。
  • 一些大一點的網站會將你的請求到反向代理服務器中,因爲當網站訪問量非常大,網站越來越慢,一臺服務器已經不夠用了。於是將同一個應用部署在多臺服務器上,將大量用戶的請求分配給多臺機器處理。此時,客戶端不是直接通過HTTP協議訪問某網站應用服務器,而是先請求到Nginx,Nginx再請求應用服務器,然後將結果返回給客戶端,這裏Nginx的作用是反向代理服務器。同時也帶來了一個好處,其中一臺服務器萬一掛了,只要還有其他服務器正常運行,就不會影響用戶使用。
  • 通過Nginx的反向代理,我們到達了web服務器,服務端腳本處理我們的請求,訪問我們的數據庫,獲取需要獲取的內容等等,當然,這個過程涉及很多後端腳本的複雜操作。由於對這一塊不熟,所以這一塊只能介紹這麼多了。

擴展

1)什麼是反向代理?

客戶端本來可以直接通過HTTP協議訪問某網站應用服務器,網站管理員可以在中間加上一個Nginx,客戶端請求Nginx,Nginx請求應用服務器,然後將結果返回給客戶端,此時Nginx就是反向代理服務器。

7、服務器返回一個 HTTP 響應 

  經過前面的6個步驟,服務器收到了我們的請求,也處理我們的請求,到這一步,它會把它的處理結果返回,也就是返回一個HTPP響應。

HTTP響應與HTTP請求相似,HTTP響應也由3個部分構成,分別是:

  • 狀態行
  • 響應頭(Response Header)
  • 響應正文

狀態行:

狀態行由協議版本、數字形式的狀態代碼、及相應的狀態描述,各元素之間以空格分隔。

-- 協議版本:是用http1.0還是其他版本

-- 狀態描述:狀態描述給出了關於狀態代碼的簡短的文字描述。比如狀態代碼爲200時的描述爲 ok

-- 狀態代碼:狀態代碼由三位數字組成,第一個數字定義了響應的類別,且有五種可能取值。

響應頭:

  響應頭部:由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號":"分隔,典型的響應頭有:

 

響應正文

包含着我們需要的一些具體信息,比如cookie,html,image,後端返回的請求數據等等。這裏需要注意,響應正文和響應頭之間有一行空格,表示響應頭的信息到空格爲止

8、瀏覽器顯示 HTML

  在瀏覽器沒有完整接受全部HTML文檔時,它就已經開始顯示這個頁面了,瀏覽器是如何把頁面呈現在屏幕上的呢?不同瀏覽器可能解析的過程不太一樣,這裏我們只介紹webkit的渲染過程,下圖對應的就是WebKit渲染的過程,這個過程包括:

解析html以構建dom樹 -> 構建render樹 -> 佈局render樹 -> 繪製render樹

 

  瀏覽器在解析html文件時,會”自上而下“加載,並在加載過程中進行解析渲染。在解析過程中,如果遇到請求外部資源時,如圖片、外鏈的CSS、iconfont等,請求過程是異步的,並不會影響html文檔進行加載。

  解析過程中,瀏覽器首先會解析HTML文件構建DOM樹,然後解析CSS文件構建渲染樹,等到渲染樹構建完成後,瀏覽器開始佈局渲染樹並將其繪製到屏幕上。這個過程比較複雜,涉及到兩個概念: reflow(迴流)和repain(重繪)。

  DOM節點中的各個元素都是以盒模型的形式存在,這些都需要瀏覽器去計算其位置和大小等,這個過程稱爲relow;當盒模型的位置,大小以及其他屬性,如顏色,字體,等確定下來之後,瀏覽器便開始繪製內容,這個過程稱爲repain。

  頁面在首次加載時必然會經歷reflow和repain。reflow和repain過程是非常消耗性能的,尤其是在移動設備上,它會破壞用戶體驗,有時會造成頁面卡頓。所以我們應該儘可能少的減少reflow和repain。 

  當文檔加載過程中遇到js文件,html文檔會掛起渲染(加載解析渲染同步)的線程,不僅要等待文檔中js文件加載完畢,還要等待解析執行完畢,纔可以恢復html文檔的渲染線程。因爲JS有可能會修改DOM,最爲經典的document.write,這意味着,在JS執行完成前,後續所有資源的下載可能是沒有必要的,這是js阻塞後續資源下載的根本原因。所以我明平時的代碼中,js是放在html文檔末尾的。

  JS的解析是由瀏覽器中的JS解析引擎完成的,比如谷歌的是V8。JS是單線程運行,也就是說,在同一個時間內只能做一件事,所有的任務都需要排隊,前一個任務結束,後一個任務才能開始。但是又存在某些任務比較耗時

  JS的執行機制就可以看做是一個主線程加上一個任務隊列(task queue)。同步任務就是放在主線程上執行的任務,異步任務是放在任務隊列中的任務。所有的同步任務在主線程上執行,形成一個執行棧;異步任務有了運行結果就會在任務隊列中放置一個事件;腳本運行時先依次運行執行棧,然後會從任務隊列裏提取事件,運行任務隊列中的任務,這個過程是不斷重複的,所以又叫做事件循環(Event loop)。

 

9、瀏覽器發送請求獲取嵌入在 HTML 中的資源(如圖片、音頻、視頻、CSS、JS等等)

  其實這個步驟可以並列在步驟8中,在瀏覽器顯示HTML時,它會注意到需要獲取其他地址內容的標籤。這時,瀏覽器會發送一個獲取請求來重新獲得這些文件

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章