瀏覽器內輸入網址到顯示網頁全過程及相關問題


在瀏覽器輸入URL到把網頁顯示出來是一個很復雜的過程,其大致流程如下圖所示:

1、DNS解析

什么是DNS解析?當用戶輸入一個網址並按下回車鍵的時候,瀏覽器得到了一個域名。而在實際通信過程中,我們需要的是一個IP地址。因此我們需要先把域名轉換成相應的IP地址,這個過程稱作DNS解析。

  1. 請求一旦發起,瀏覽器首先要做的就是解析這個域名,一般瀏覽器會首先搜索自身緩存的DNS記錄,比如chrome緩存1000條DNS解析結果;
  2. 當瀏覽器緩存中沒有找到需要的記錄或者記錄已經過期,則會查看本地硬盤的hosts文件,看看其中有沒有和這個域名對應的規則,如果有的話就直接使用 hosts 文件里面的 ip 地址。(windows中可以通過 ipconfig / displaydns 命令查看本機當前的緩存);通過hosts文件, 可以手動指定一個域名和其對應的IP解析結果,並且該結果一旦被使用,同樣可以緩存到hosts中,linux系統的hosts文件在/etc/hosts下面;
  3. 如果本地的hosts文件中沒有找到對應的ip地址或者記錄已經過期,則需要發送一個域名解析請求到本地域名解析服務器,本地DNS服務器會首先查詢它的緩存記錄,如果緩存中有此條記錄,就可以直接返回
    結果;如果沒有,本地DNS服務器還要向DNS根域服務器進行查詢。(一般來說就是電腦上配置的DNS服務器一項)。一般一台域名解析服務器會被地理位置臨近的大量用戶使用(特別是ISP的DNS,如中國聯通、中國移動),一般常見的網站域名解析都能在這里命中;
  4. 假設要解析的域名是mail.google.com,本地DNS服務器中是沒有查到的,便向根域服務器發送請求(注:根域服務器全球只有13台,所以不可能把所有的IP地址都記錄下來,記錄的是com域服務器的IP、cn域服務器IP的IP等等,如下圖所示)。
    很顯然根域服務器上沒有mail.google.com的IP,但是卻有com域服務器的IP,所以根域服務器就把com域服務器的IP告訴本地DNS服務器,本地DNS服務器便到.com域服務器中去查找mail.google.com的IP;同樣.com域服務器中也沒有mail.google.com的IP,但是卻有.google.com域服務器 的IP,接着我們的域名解析服務器會向google.com域服務器發出請求。如此重復,得到mail.google.com的IP地址。
  5. 當獲取域名對應的IP地址后,本地DNS服務器不僅要把IP地址返回給用戶電腦,還要把域名和ip地址的對應關系保存在緩存中,以備下次別的用戶查詢時,可以直接返回結果,加快網絡訪問。
    遞歸查詢和迭代查詢
    • 遞歸查詢:主機向本地域名服務器的查詢一般都是采用遞歸查詢。所謂遞歸查詢就是:如果主機所詢問的本地域名服務器不知道被查詢域名的IP地址時,那么本地域名服務器就以DNS客戶的身份,向其他根域名服務器繼續發出查詢請求報文(即替代該主機繼續查詢),而不是讓該主機自己進行下一步的查詢。因此,遞歸查詢返回的查詢結果或者是所要查詢域名對應的IP地址,或者是報錯,無法查詢到所需的IP地址。
    • 迭代查詢:本地域名服務器向根域名服務器的查詢通常是采用迭代查詢。迭代查詢的特點是:當根域名服務器發出的迭代查詢請求報文時,要么給出所要查詢的IP地址,要么告訴本地域名服務器,“你下一步應該向哪一個域名服務器進行查詢”。

然后讓本地域名服務器進行后面的查詢(而不是替代本地域名服務器進行后續的查詢)。如此重復,最終得到所要查詢的IP地址,或者是沒查到。當然本地域名服務器也可以采用遞歸查詢,這取決於最初的查詢請求報文的設置是要求使用哪一種
查詢方式。兩種查詢方式如下圖所示,(圖片來源網絡,侵刪)

2、發送HTTP請求

當瀏覽器獲取到域名對應的IP地址后,會以一個隨機端口(1024,65535)向服務器的web程序80端口發送TCP的連接請求。這個連接請求到達服務器端后(這中間通過各種路由設備,局域網內除外),進入到網卡,然后是進入到內核的TCP/IP協議棧
(用於識別該連接請求,解封包,一層一層的剝開),還有可能要經過Netfilter防火牆(屬於內核的模塊)的過濾,最終到達WEB程序,最終建立了TCP/IP的連接。

1、TCP三次握手連接,如下圖所示:

  • 客戶端進行首先創建傳輸控制模塊TCB(傳輸控制塊TCB存儲了每一個連接中的一些重要的信息,如TCP連接表、指向發送和緩存的指針,指向重傳隊列的指針,當前的發送和接受序號等),然后向服務器發出連接請求報文段,這時首部中的同步位SYN=1,同時選擇一個初始序號seq=J。TCP規定,SYN報文段(即SYN=1的報文段)不能攜帶數據,但要消耗掉一個序號。這時客戶端進程進入SYN-SENT
    (同步已發送)狀態;
  • 服務器收到請求報文段后,如果同意建立連接,則向客戶端發送確認。在確認報文段中應把SYN位和ACK位都置為1,確認號是ack=J+1,同時為自己選擇一個初始序號seq=K。請注意,這個報文段也不能攜帶數據,但同樣要消耗掉一個序號。當服務器把這個報文段發送給客戶端后,便進入SYN-RCVD(同步收到)狀態;
  • 客戶端收到服務器的確認后,檢查確認號ack是否為J+1(確保收到的確認是服務器對自己發出連接請求的確認),以及報文段首部的ACK是否為1,如果正確則將自己的ACK置為1,ack置為K+1。TCP的標准規定,ACK報文段可以攜帶數據,但是如果不攜帶數據則不消耗序號。當客戶端把該數據包發送給服務端時,服務端檢查ack是否為K+1,ACK是否為1,如果正確則連接建立成功,客戶端和服務器進入ESTABLISHED狀態,完成三次握手,隨后客戶端和服務器就可以進行數據的傳輸了。所以在TCP三次握手中,第三次握手是可以攜帶數據的。

三次握手相關問題

  1. 為什么一定要三次握手?

    1. 簡單來說,三次握手的目的是為了讓雙方驗證各自的接收能力和發送能力。《計算機網絡》第四版中講“三次握手”的目的是“為了防止已失效的連接請求報文段突然又傳送到了服務端,因而產生錯誤”

    2. 書中的例子是這樣的,“已失效的連接請求報文段”的產生在這樣一種情況下:client發出的第一個連接請求報文段並沒有丟失,而是在某個網絡結點長時間的滯留了,以致延誤到連接釋放以后的某個時間才到達server。本來這是一個早已失效的報文段。但server收到此失效的連接請求報文段后,就誤認為是client再次發出的一個新的連接請求。於是就向client發出確認報文段,同意建立連接。

    3. 假設不采用“三次握手”,那么只要server發出確認,新的連接就建立了。由於現在client並沒有發出建立連接的請求,因此不會理睬server的確認,也不會向server發送數據。但server卻以為新的運輸連接已經建立,並一直等待client發來數據。這樣,server的很多資源就白白浪費掉了。采用“三次握手”的辦法可以防止上述現象發生。例如剛才那種情況,client不會向server的確認發出確認。server由於收不到確認,就知道client並沒有要求建立連接。”。主要目的防止server端一直等待,浪費資源。

  2. 假設A和B同時互相發送TCP連接請求會發生什么?建立幾個連接?

    1. 三次握手是建立TCP連接的過程,由於雙方成功握手后會在兩個應用程序之間建立一個全雙工的通信,所以最終A和B只會建立一個連接,可以互相發送數據。
  3. 客戶端正在和服務端建立TCP連接,然而當服務器變為SYN-RCVD后,此時一個舊的SYN報文又到達了,服務器會如何處理?

    1. 由於服務器端在SYN-RCVD狀態下,接收到舊的SYN報文時是不能作出判斷的,所以會照常返回;當客戶端接收到該報文后發現異常,才會發送RTS報文,重置連接。
  4. 一個TCP連接可以發送多個HTTP請求?

    1. 參考:https://zhuanlan.zhihu.com/p/348023442

    2. 在HTTP/1.0中,一個服務器發送完一個HTTP響應后,會斷開TCP連接。但是這樣每次請求都會重新建立和斷開TCP連接,代價過大。所以雖然標准中沒有設定,某些服務器對Connection: keep-alive 的 Header 進行了支持。意思是說,完成這個 HTTP 請求之后,不要斷開 HTTP 請求使用的 TCP 連接。這樣的好處是連接可以被重新使用,之后發送 HTTP 請求的時候不需要重新建立 TCP 連接,以及如果維持連接,那么 SSL 的開銷也可以避免。

    3. 在HTTP/1.1中,就把Connection頭寫入標准,並且默認開啟持久連接(keep-alive),除非請求中寫明Connection:close,那么瀏覽器和服務器之間是會維持一段時間的TCP連接,不會一個請求就斷掉。所以,如果維持TCP的連接,一個TCP連接是可以發送多個HTTP請求的。 那么客戶端如何判斷服務器的數據已經發成完成?

      1. 使用消息首部字段Content-Length:Content-length表示實體內容長度,客戶端(服務器)可以根據這個值來判斷數據是否接收完成。這適用於客戶端向服務器請求的是靜態資源,服務器可以很清楚的知道內容大小。
      2. 如果請求的是動態資源,服務器不可能提前知道內容大小,這時候可以使用Transfer-Encoding:chunk 模式來傳輸數據,是分塊傳輸的,chunked編碼的數據在最后有一個空chunked塊,表明本次傳輸數據結束。
      3. 參考鏈接:https://www.cnblogs.com/skynet/archive/2010/12/11/1903347.html
    4. HTTP/1.1中的一個TCP連接是可以發送多個HTTP請求的,但是單個TCP連接在同一時刻只能處理一個請求,意思就是說:兩個請求的生命周期不能重疊,任意兩個HTTP請求從開始到結束的時間在同一個TCP連接里不能重疊。雖然HTTP/1.1規范中規定了Pipelining來試圖解決這個問題,但是這個功能在瀏覽器中默認是關閉的,在實踐中會出現很多問題。

    5. 上面說道,一個支持持久連接的客戶端可以在一個TCP連接中發送多個請求(不需要等待任意請求的響應)。收到請求的服務器必須按照請求收到的順序發送響應。這是由於HTTP/1.1 是個文本協議,同時返回的內容也並不能區分對應於哪個發送的請求,所以順序必須維持一致。

    6. HTTP2提供了Multiplexing多路傳輸特性,可以在一個TCP連接中同時完成多個HTTP請求(並行進行)。

      1. 同域名下所有通信都在單個連接上完成,消除了因多個TCP連接而帶來的時延和消耗;
      2. 單個連接上可以並行交錯的請求和響應,之間互不干擾。
    7. 在HTTP/1.1時代,瀏覽器提高頁面加載效率主要有兩點:

      1. 維持和服務器已經建立的TCP連接,在同一連接上順序處理多個請求;
      2. 和服務器建立多個TCP連接(瀏覽器為了控制資源,有6-8個TCP連接的限制)。
  5. TCP如何保證連接的唯一性:TCP的源端口、目的端口、以及IP層的源IP地址、目的IP地址四元組唯一的標識了一個TCP連接;

  6. 第三次握手失敗了怎么辦?

    1. 當客戶端收到服務端的SYN-ACK應答后,其狀態變為ESTABLISHED,同時向服務端發送一個ACK包,如果此時ACK包丟失,那么服務端在過了超時計時器后,會重新發送SYN-ACK包,超過重傳次數(默認)后,服務端自動關閉這個連接。
    2. 如果服務端此時處於CLOSED,當接收到連接已關閉的請求時,服務端會返回RST報文,客戶端接收后會關閉連接,如果需要的話會重連,那么就是另一個三次握手了。
    3. 當服務端處於SYN-RCVD,此時如果接收到正常ACK報文,就恢復連接,繼續傳輸數據。
  7. 如果已經建立了連接,但是客戶端突然出現了故障:TCP會專門設置一個保活計時器,顯然當建立連接后,客戶端出現故障的話,服務器不能一直等待下去,白白浪費資源。服務端每收到一次客戶端的請求后會復位這個計時器,時間通常是2小時,若2h還未收到客戶端的任何數據,服務器就會發送一個探測報文段,以后每隔75s發送一次。若一連發送10個探測報文仍然沒有反應,服務器就認為客戶端發送了故障,接着就關閉連接。

  8. 建立連接三次握手,而關閉連接時四次揮手的原因:當服務端收到客戶端發送的SYN連接請求報文后,可以直接發送SYN+ACK報文,同意與客戶端建立連接。但是當關閉連接時,服務端收到的是客戶端發來的FIN報文(此時客戶端已經沒有要向服務端發送的數據,但是客戶端還能接收來自服務端的數據),那么服務端有可能仍有數據還未發送完,所以不會關閉socket,只能回復一個ACK報文,表明已經收到來自客戶端的關閉請求。當服務端把要發送的數據發送完之后,才會發送一個FIN報文,然后客戶端再針對這個FIN發送ACK,所以需要四次揮手。

  9. 四次揮手中的CLOSE_WAIT是服務端接受到客戶端關閉請求后、仍向客戶端發送數據的狀態。

  10. 為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能返回到CLOSE狀態?

    1. 最后一個ACK有可能丟失。TIME_WAIT狀態是客戶端用來重發可能丟失的ACK報文。當服務端發送FIN報文、Client對這個報文發送ACK后,進入TIME_WAIT狀態,等待2MSL。此時若服務端成功接收來自客戶端的ACK時,就什么也不做;若沒有收到ACK時,將會重復發送FIN。所以客戶端在TIME_WAIT等待的2MSL時間內,若再次收到了來自服務端的FIN,就會重發ACK並再次等待2MSL;如果直到2MSL,Client都沒有再次收到FIN,則表明服務端已經收到了客戶端的ACK,結束TCP連接。(MSL指的就是一個片段在網絡中最大的存活時間,2MSL就是一個發送和一個回復所需的最大時間)。
    2. 客戶端在發送完最后一個ACK報文段時,再經過2MSL,就可以使本連接持續的時間內所產生的所有報文段都從網絡中消失,使下一個新的連接中不會出現這種舊的連接請求報文段。
  11. 大量TIME-WAIT問題:首先明白,TIME-WAIT是客戶端的階段(主動發起關閉的那一方)。在高並發短連接情況下,當處理完請求后主動關閉連接。這個場景下會出現大量TIME-WAIT狀態。例如爬蟲服務器,對於它來說,自身就是客戶端,在完成一個爬取任務后就會發起主動關閉連接,從而進去TIME-WAIT狀態,然后保持這個狀態2MSL時間之后,徹底關閉回收資源。這段時間會出現大量TIME-WAIT狀態。解決辦法如下:

    1. 設置SO_REUSEADDR套接字選項來通知內核,如果端口忙、但是TCP連接處於TIME-WAIT狀態下,可以重用端口;
    2. 由於TIME_WAIT狀態是在主動關閉的一方出現的,所以在設計邏輯的時候,應該盡量由客戶端主動關閉,避免服務端出現TIME_WAIT狀態;
    3. 通過調整內核參數解決(開啟重用、TIME-WAIT快速回收)
  12. 大量CLOSE-WAIT狀態:四次揮手期間,服務端因故沒有向客戶端發出FIN包,所以出現大量CLOSE-WAIT現象,主要原因是某種情況下對方關閉了SOCKET連接,但是我方忙於讀寫,沒有關閉連接。

  13. Nagle算法:Nagle算法主要是用來避免發送小的數據包,通過減少需要通過網絡發送包的數量來提高TCP/IP傳輸的效率。主要做了兩件事:

    1. 只允許一個未被ACK的分組存在於TCP連接上,在該分組的確認到達之前不能發送其他的小分組。也就是說只有上一個分組得到確認后,才會發送下一個分組。
    2. Nagle算法將多次間隔較小、數據量較小的數據合並成一個數據量大的數據塊,在一個確認到來時一起發送。
  14. TCP粘包問題:TCP粘包就是指發送方發送的若干[數據包]到達接收方時粘成了一個包,從接收緩沖區來看,后一個包數據的頭緊接着前一個包的數據的尾,出現粘包的原因是多方面的,可能是來自發送包,也可能來自接收方。

    1. 發送方:
      1. TCP默認使用Nagle算法(如上面所示),Nagle算法造成了發送方可能出現粘包問題;
      2. 解決辦法:通過設置TCP_NODELAY關閉Nagle算法。
    2. 接收方:
      1. 接收數據端的應用層沒有及時讀取緩沖區中的數據,也將發生粘包。
      2. 解決辦法:明確兩個包之間的邊界。設計一個帶包頭的應用層報文結構。包頭定長,以特定標志開頭,里面帶着負載長度,這樣接收端側只要以定長嘗試讀取包頭,再按照包頭里的負載長度讀取負載就行了,多出來的數據留在緩沖區即可。(ip報文和TCP報文都是這么干的)
  15. SYN洪范攻擊:服務端收到客戶端的SYN報文同意連接后,向客戶端發送SYN-ACK報文時,會為客戶端的請求分配內存。攻擊者就可以使用一批虛假的IP向服務器大量地建立TCP連接的請求,服務器為這些虛假IP分配了緩存后,處在SYN_RCVD狀態,存放在半連接隊列中;但是服務器發送的請求是不可能得到回復的,因為這些ip都是虛假的,直到設定的次數或時間后,才會關閉。服務器不斷的為這些半開連接分配資源,導致服務器的連接資源被消耗殆盡。使用SYN cookie來解決。
    參考鏈接:https://zhuanlan.zhihu.com/p/103000747

  16. TCP分段和IP分片

    1. 分段特指發生在TCP協議的傳輸層中的數據切分行為,分片特指發生在使用IPv4協議的網絡IP層中的數據切分行為。
    2. 最大傳輸單元(Maximum Transmission Unit)即MTU,為數據鏈路層的最大載荷上限(例如二層協議為以太網時,MTU為1500字節),一個數據包在傳輸過程中如果它的長度(IP首部+載荷部分)超過當前鏈路的MTU,就要進行分片傳輸,使得每個IP數據報大小不超過MTU;最大報文段長度(Maximum Segment Size,MSS)為TCP傳輸層的最大載荷上限(即應用層數據最大長度),取決於通信雙方較小的那一個MSS值,與MTU的換算關系為MTU=MSS + TCP 首部長度 + IP首部長度,要傳輸的TCP報文段大於MSS值時,需要進行分段處理。由於MSS是由MTU推導而來,所以發送端在TCP分段之后就一定不會再網絡層發生IP分片,若傳輸經過的鏈路MTU仍比當前IP數據報長度大,也可能會發生IP分片。如果兩個通信主機直連,TCP分段之后就不會發生TCP分片。
    3. TCP可以通過路徑MTU發現來獲取鏈路中的最小MTU,避免IP分片。
    4. 參考鏈接:https://cloud.tencent.com/developer/article/1173790

2、TCP四次揮手,如下圖所示

  • 數據傳輸結束后,通信的雙方都可以釋放連接。現在客戶端和服務器都處於ESTABLISHED狀態,客戶端A的應用進程首先向其TCP發送連接釋放報文段,並停止再發送數據,主動關閉TCP連接。A把連接釋放報文段首部的終止控制位FIN置為1,其序號seq=u,它等於前面已傳送的數據的最后一個字節的序號加1。這時A進入FIN-WAIT-1(終止等待1)狀態,等待B的確認。TCP規定,即使FIN報文段不攜帶數據,也會消耗一個序號。
  • 服務器B收到連接釋放報文段后立即發出確認,確認號ack=u+1,這個報文段字節的序號為v,v=前面已傳送過的數據的最后一個字節的序號加1。然后B就進入CLOSE_WAIT(關閉等待)狀態。TCP服務器進程這時應通知高層應用進程,因為從A到B這個方向的連接就釋放了,但是此時TCP還是處於半連接狀態,即A已經沒有數據要發送了,但是B若要發送數據,A仍可以接收。也就是說,從B到A這個方向的連接並未關閉,這個狀態可能會持續一段時間。A收到來自B的確認后,就進入FIN-WAIT-2(終止等待2)狀態,等待B發出的連接釋放報文段。
  • 若B已經沒有要向A發送的報文段時,其應用進程就通知TCP釋放連接。這時B發出的報文段中FIN=1,現假定B的序號為w(在半關閉狀態,B又可能向A發送了一些數據)。B還必須重復上次已發送過的確認號ack=u+1。這時B進入LAST-ACK(最后確認狀態),等待A的確認。
  • A在收到B的連接釋放報文段后,必須對此發出確認,在確認報文段中,把ACK置為1,確認號ack置為w+1,而自己的序號是u+1(根據TCP標准,前面發送過的FIN報文段要消耗一個序號)。然后進入TIME-WAIT(時間等待階段)狀態。請注意,現在的TCP連接還未釋放掉,必須等待時間等待計時器設置的2MSL后,A才進入到CLOSED狀態。

成功建立TCP連接之后,就會發起一個HTTP請求。

3、 HTTP

  • HTTP是一種無狀態、由文本構成的請求-響應協議,這種協議使用的是客戶端-服務器計算模型。無狀態意味着它唯一知道的就是客戶端會向服務器發送請求,而服務器則會向客戶端返回響應,並且后續發生的請求對之前發送過的請求一無所知。常用的HTTP請求方法包括GET和POST等,GET是命令服務器返回指定的資源;POST與命令服務器將報文主體的數據傳遞給URI指定的資源,至於服務器具體會對這些數據執行什么動作取決於服務器本身。
  • 與使用純文本方式表示的HTTP1.x不同,HTTP/2是一種二進制協議:二進制表示不僅能夠讓HTTP/2的語法分析變得更為高效,還能夠讓協議變得更為緊湊和健壯;但是對於那些習慣了使用HTTP1.x的開發者來說,無法再通過telnet等應用程序直接發送HTTP/2報文來進行調試。
  • 同時,HTTP1.x在一個網絡連接中每次只能發送單個請求,而HTTP/2是完全多路復用的,這意味着多個請求和響應可以在同一時間內使用同一個連接。除此之外,HTTP/2還會對首部進行壓縮以減少需要傳送的數據量,並允許服務器將響應推送至客戶端,這些措施都有效地提升性能。但是方法和狀態碼上來說,HTTP1.x和HTTP/2還是一樣的。

4、 HTTPS

3、負載均衡

經過前面的重重步驟,服務器端終於收到了我們的HTTP請求。如果我們的平台配置了反向代理的話,前一步DNS解析得到的IP地址就是我們Ngnix負載均衡服務器的IP地址。

  1. 首先來介紹一下反向代理,如下圖所示,客戶端本來可以直接通過HTTP協議訪問到某網站服務器,當網站的訪問量非常大時,網站會越來越慢,一台服務器已經不夠用了,於是網站管理員將同一個應用部署到多台服務器上,將大量用戶的請求分配給多台機器處理。此時當用戶發送HTTP請求時,首先到達Nginx負載均衡服務器上,Nginx根據設定的分配算法和規則,選擇一台正式的web應用服務器,與之建立TCP連接並轉發瀏覽器發出去的網頁請求。這里的Nginx作用就是反向代理服務器。同時也帶來了一個好處,其中一台服務器萬一掛了,只要還有其他服務器正常運行,就不會影響用戶使用。

    Nginx默認支持RR輪轉法和ip_hash這兩種分配算法。前者會從頭到尾一個個輪詢所有Web服務器,而后者則對源IP使用hash函數確定應該轉發到哪個Web服務器上,也能保證同一個IP的請求能發送到同一個Web服務器上實現會話粘連。

  2. web服務器收到請求並產生響應,將網頁發送給Nginx輔助均衡服務器。Nginx負載均衡服務器將網頁傳遞給filters鏈處理,之后發回給我們的瀏覽器。如圖所示,Filter的功能可以理解成先把前一步生成的結果處理一遍,再返回給瀏覽器。比如可以將前面沒有壓縮的網頁用gzip壓縮后再返回給瀏覽器。

4、web服務器響應

HTTP響應與HTTP請求相似,同樣有響應頭(請求頭),這里列一下響應的狀態碼:

  1. 1xx:信息性狀態碼,表示服務器已接收了客戶端請求,客戶端可繼續發送請求。

    1. 100 Continue:客戶端應繼續其請求;
    2. 101 Switching Protocols:切換協議,服務器根據客戶端的請求切換協議,只能切換到更高級的協議,例如切換到HTTP的新版本協議。
  2. 2xx:成功狀態碼,表示服務器已成功接收到請求並進行處理。

    1. 200 OK:表示客戶端請求成功,一般用於GET和POST請求;
    2. 204 No Content:成功,但不返回任何實體的主體部分;
    3. 206 Partial Content:成功執行了一個范圍(Range)請求;
  3. 3xx: 重定向狀態碼,表示服務器要求客戶端重定向。

    1. 301 Moved Permanently:永久性重定向,資源(網頁等)被永久轉移到其他URL ,新URL會在響應頭的Location中給出。
    2. 302 Found:臨時性重定向,響應報文的Location首部給出的URL用來臨時定位資源;
    3. 303 See Other:請求的資源存在着另一個URI,客戶端應使用GET方法定向獲取請求的資源;
    4. 304 Not Modified:服務器內容沒有更新,可以直接讀取瀏覽器緩存;
    5. 305 Use Proxy:使用代理,所請求的資源必須通過代理訪問;
    6. 307 Temporary Redirect:臨時重定向。與302 Found含義一樣。302禁止POST變換為GET,但實際使用時並不一定,307則更多瀏覽器可能會遵循這一標准,但也依賴於瀏覽器具體實現;
    7. 轉發和重定向的區別:
      1. 轉發(forward)是服務器內部行為,服務器直接向目標地址訪問URL,將相應的內容讀取之后發送給瀏覽器,瀏覽器中URL的變化是看不到的,並且轉發時原來攜帶的參數仍然可以使用;
      2. 重定向(redirect)是客戶端層面的,利用服務器返回的狀態碼來實現的,如果服務器返回301或302,瀏覽器收到新的消息后自動跳轉到新的網址重新請求資源。用戶的地址欄URL會發生變化,而且不能共享數據。
  4. 4xx:客戶端錯誤狀態碼,表示客戶端的請求有非法內容。

    1. 400 Bad Request:表示客戶端請求有語法錯誤,不能被服務器所理解;
    2. 401 Unauthonzed:表示請求未經授權,該狀態代碼必須與 WWW-Authenticate 報頭域一起使;
    3. 403 Forbidden:表示服務器收到請求,但是拒絕提供服務,通常會在響應正文中給出不提供服務的原因;
    4. 404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL
    5. 405 Method Not Allowed:客戶端請求中的方法被禁止
    6. 408 Request Time-out:服務器等待客戶端發送的請求時間過長,超時
  5. 5xx:服務器錯誤狀態碼,表示服務器未能正常處理客戶端的請求而出現意外錯誤。

    1. 500 Internel Server Error:服務器內部錯誤(不可預期的錯誤),無法完成請求;
    2. 501 Not Implemented:服務器不支持請求的功能,無法完成請求;
    3. 502 Bad Gateway:作為網關或者代理工作的服務器嘗試執行請求時,從遠程服務器收到了一個無效的響應;
    4. 503 Service Unavailable:表示服務器當前不能夠處理客戶端的請求,在一段時間之后,服務器可能會恢復正常;
    5. 504 Gateway Time-out:充當網關或者代理的服務器,未及時從遠端服務器獲取請求;
    6. 505 HTTP version not supported:服務器不支持請求的HTTP協議的版本,無法完成處理。

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

  1. 網站調整(如改變網頁目錄結構);
  2. 網頁被移到一個新地址;
  3. 網頁擴展名改變(如應用需要把.php改成.Html或.shtml)。

這種情況下,如果不做重定向,則用戶收藏夾或搜索引擎數據庫中舊地址只能讓訪問客戶得到一個404頁面錯誤信息,訪問流量白白喪失;再者某些注冊了多個域名的網站,也需要通過重定向讓訪問這些域名的用戶自動跳轉到主站點等。
當一個網站或者網頁24—48小時內臨時移動到一個新的位置,這時候就要進行302跳轉,而使用301跳轉的場景就是之前的網站因為某種原因需要移除掉,然后要到新的地址訪問,是永久性的。
清晰明確而言:使用301跳轉的大概場景如下:

  1. 域名到期不想續費(或者發現了更適合網站的域名),想換個域名。
  2. 在搜索引擎的搜索結果中出現了不帶www的域名,而帶www的域名卻沒有收錄,這個時候可以用301重定向來告訴搜索引擎我們目標的域名是哪一個。
  3. 空間服務器不穩定,換空間的時候。

5、瀏覽器顯示

1) 瀏覽器渲染

瀏覽器根據頁面內容,生成DOM Tree。根據CSS內容,生成CSS Rule Tree(規則樹),調用JS執行引擎執行JS代碼;根據DOM Tree和CSS Rule Tree生成Render Tree(呈現樹);根據Render Tree渲染網頁。

2) 網站靜態資源加載

不像動態網頁,靜態文件允許瀏覽器對其進行緩存。有的文件可能會不需要與服務器通訊,可從緩存中直接讀取。可將這些靜態資源放在CDN中,提高加載速度。

什么是CDN?如果我在廣州訪問杭州的淘寶網,跨省的通信必然造成延遲。如果淘寶網能在廣東建立一個服務器,靜態資源我可以直接從就近的廣東服務器獲取,必然能提高整個網站的打開速度,這就是CDN。CDN,內容分發網絡,是依靠部署在各地的邊緣服務器,使用戶就近獲取所需內容,降低網絡擁塞,提高用戶訪問響應速度。

至此,瀏覽器便顯示出來了。
參考博文:

https://xianyulaodi.github.io/2017/03/22/老生常談-從輸入url到頁面展示到底發生了什么/#9、瀏覽器發送請求獲取嵌入在-HTML-中的資源(如圖片、音頻、視頻、CSS、JS等等)

https://www.jianshu.com/p/635503c40601


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM