1. 程式人生 > >瀏覽器一個請求的過程【轉】

瀏覽器一個請求的過程【轉】

瀏覽器一個請求的過程

當我們在瀏覽器位址列輸入 www.xx.com ,然後回車, 這個請求背後經歷了什麼?以下是個人理解,如有偏差,請糾正!

首先重新溫習下網路模型:

  • 七層結構(至頂向下):應用層、表示層、會話層、傳輸層、網路層、資料鏈路層、物理層

這裡寫圖片描述

client(瀏覽器) 與Server 通過HTTP協議通訊,HTTP協議屬於”應用層協議”;HTTP基於TCP協議,TCP通過Socket進行通訊,TCP 被稱為“傳輸層協議”。而HTTPS 還需要走會話層SSL\TLS等協議;傳輸層之下是網路層,這裡主要是路由協議OSPF等進行路由選擇,轉發;再向下資料鏈路層主要是ARP、RARP協議完成IP和MAC地址互相解析,再向下是物理層主要是基於IEEE802.X等協議進行資料位元流轉成高低電平的定義;

當瀏覽器發出請求時候,首先通過應用層DNS協議得到對應IP地址,在這經歷全球路由大接力;而傳輸層TCP協議採用“三次握手”協議建立連線和“四次握手”協議斷開連線,然後資料鏈路層解析IP與MAC地址的對映;資料經過層層資料封包、解包過程,如下:這裡寫圖片描述

這裡特別強調下三次握手建立連線,放圖作為參考:這裡寫圖片描述

Wireshark中抓包圖,如下:這裡寫圖片描述

四次握手斷開連線:這裡寫圖片描述

客戶端發起 FIN ACK, 服務端應答 ACK, 待服務端資料傳送完成後,傳送FIN ACK, 客戶端應答 ACK, 連線斷開。這裡寫圖片描述

注: WireShark中“四次握手“的資料並不一定會在一起。

從應用服務角度分析

資料交換主要通過HTTP 協議, HTTP協議是無狀態協議。多數通過GET、POST方法,GET與POST區別: GET:請求獲取指定的資源,不改變伺服器狀態,GET方法是冪等的,GET方法的報文主體沒有任何語義。 POST: 根據請求報文主體對指定的資源做出處理,改變伺服器狀態,POST方法不冪等。

http方法不僅只有GET、POST, http1.1中含有如下方法:這裡寫圖片描述

RESTful API 就是利用這組方法來統一表述資源的狀態轉化。

同時,由於http無狀態協議的特點,服務端需要記錄使用者時,就需要用某種機制來識具體的使用者, 通常採用cookies、session。

session 本意是會話,是一個抽象概念。將 clinet 和 server 之間一對一的互動,抽象為“會話”,開發者為了實現一對一的“隔離”,中斷和繼續等操作,進而衍生出“會話狀態”,也就是 session 的概念。

如何維護這個session概念,很自然的想到在http請求報文中加入登入標識就可以了,這個登入標識就是cookie。而 cookie 是一個實際存在的東西,http 協議中定義在 header 中的欄位。這種技術的實現就是利用了cookie技術。 cookie是儲存key-value對的一個檔案,務必記住,它是由伺服器將cookie新增到response裡一併返回給客戶端,然後客戶端會自動把response裡的cookie接收下來,並且儲存到本地,下次發出請求的時候,就會把cookie附加在request裡,伺服器在根據request裡的cookie遍歷搜尋是否有與之符合的資訊。

cookie 雖然很方便,但是使用 cookie 有兩個的弊端:

  1. cookie 中的所有資料在客戶端就可以被修改。這就意味著資料非常容易被偽造,一些重要的資料就不能存放在 cookie 中;
  2. 如果 cookie 中資料欄位太多會影響傳輸效率;

為了解決這些問題,就產生了 session, session是一種伺服器機制,使用Hash散列表結構來儲存資訊。 1. 每個 session 都對應一個 session_id,通過 session_id 可以查詢到對應的 session; 2. session_id 通常是存放在客戶端的 cookie 中,服務端存好 session 之後將對應的 session_id 設定在 cookie 中傳送給客戶端; 3. 當請求到來時,服務端檢查 cookie 中儲存的 session_id 並通過這個 session_id 與伺服器端的 session 關聯起來,進行資料的儲存和修改;

這就是大多數人通常所說的session, 這裡其實是指的 session實現。

server 端通常採用Nginx、Apache;

這裡以PHP為例: Nginx接收到請求,進行一些驗證,如黑白名單攔截等, 是否有限流限制,是否有負載均衡設定; 如果請求的是靜態內容,Nginx會將結果直接返回給使用者。 如果請求的是動態內容,Nginx會將請求交給fastcgi客戶端, 通過fastcgi_pass將這個請求傳送給程序php-fpm。Nginx 不支援對外部動態程式的直接呼叫或者解析 ,所有的外部程式必須通過FastCGI介面來呼叫。