1. 程式人生 > >Http 請求和響應全過程

Http 請求和響應全過程

知識儲備

HTTP無狀態性

HTTP協議是無狀態的,同一個客戶端第二次訪問同一個伺服器上的頁面時,伺服器無法知道這個客戶端曾經訪問過,伺服器也無法分辨不同的客戶端。簡化了伺服器的設計,使得伺服器更容易支援大量併發的HTTP請求

HTTP持久連線

HTTP1.0使用的是非持久連線 缺點是客戶端必須為每一個待請求的物件建立並維護一個新的連線,即每請求一個文件就要有兩倍RTT的開銷。因為一個頁面可能存在多個物件,所以非持久連線可能使一個頁面的下載變得十分緩慢,而且這種短連線增加了網路傳輸的負擔。

HTTP1.1 使用持久連線keepalive,所謂持久連線,就是伺服器在傳送響應後仍然在一段時間內保持這條連線,允許在同一個連線中存在多次資料請求和響應,即在持久連線情況下,伺服器在傳送完響應後並不關閉TCP 連線,而客戶端可以通過這個連線繼續請求其他物件。

HTTP/1.1 協議的持久連線有兩種方式

  • 非流水線方式:客戶在收到前一個響應後才能發出下一個響應
  • 流水線方式:客戶在收到HTTP響應報文之前就能接著傳送新的請求報文

HTTP請求和響應過程

1. 首先,在瀏覽器裡輸入網址

這裡寫圖片描述

2. 瀏覽器根據域名解析IP地址

這裡寫圖片描述

瀏覽器根據訪問的域名找到其IP地址。DNS查詢過程如下:

1)瀏覽器快取:瀏覽器會快取DNS記錄一段時間。 但作業系統沒有告訴瀏覽器儲存DNS記錄的時間,這樣不同瀏覽器會儲存個自固定的一個時間(2分鐘到30分鐘不等)。

2)系統快取:如果在瀏覽器快取裡沒有找到需要的域名,瀏覽器會做一個系統呼叫(windows裡是gethostbyname),這樣便可獲得系統快取中的記錄

3)路由器快取:如果系統快取也沒找到需要的域名,則會向路由器傳送查詢請求,它一般會有自己的DNS快取

4)ISP DNS快取:如果依然沒找到需要的域名,則最後要查的就是ISP快取DNS的伺服器。在這裡一般都能找到相應的快取記錄

域名解析原理

  1. 一個域中的每個主機名與其IP地址的對映關係由這個域的DNS伺服器負責管理,例如,”www.it.org”、“ftp.it.org”、“blog.it.org”等主機名都由管理域“it.org”的DNS伺服器進行管理,而不能由管理域“org”的DNS伺服器進行管理。

  2. 每個管理域都必須在其直接父域的DNS伺服器上註冊該子域的名稱和該子域的DNS伺服器的IP地址,例如,必須在管理域“org”的DNS伺服器註冊子域“it.org”和其DNS伺服器的IP地址後,域名“it.org”才能真正被外界所認可。

  3. 為了方便對頂級域名的統一管理,在頂級域名之上其實還有一個根域名,根域名用點(.)表示,例如,“www.it.org”也可以寫為“www.it.org.”,“www.it.org.”中的最後的那個點(.)就表示根域名。 Internet中的根域名由InterNIC(國際網際網路絡資訊中心)集中管理,頂級域名和其下的域名則由擁有該域名的組織、公司和個人自己管理。

域名解析的方式主要有兩種,分別是:

這裡寫圖片描述

或者

這裡寫圖片描述

DNS有一個弊端,一個域名看上去只是對應一個單獨的IP地址。還好有幾種方法可以消除這個瓶頸:

  1. 迴圈 DNS 是DNS查詢時返回多個IP時的解決方案。舉例來說,facebook.com實際上就對應了四個IP地址。
  2. 負載平衡器是以一個特定IP地址進行偵聽並將網路請求轉發到叢集伺服器上的硬體裝置。 一些大型的站點一般都會使用這種昂貴的高效能負載平衡器。
  3. 地理 DNS 根據使用者所處的地理位置,通過把域名對映到多個不同的IP地址提高可擴充套件性。這樣不同的伺服器不能夠更新同步狀態,但對映靜態內容的話非常好。
  4. Anycast 是一個IP地址對映多個物理主機的路由技術。 美中不足的是Anycast與TCP協議適應的不是很好,所以很少應用在那些方案中。大多數DNS伺服器使用Anycast來獲得高效低延遲的DNS查詢。

3. 瀏覽器與web伺服器建立一個 TCP 連線

4. 瀏覽器給Web伺服器傳送一個http請求

這裡寫圖片描述

一個http請求報文由請求行<request-line>、請求頭部<headers>、空行<blank-line>和請求資料<request-body>4個部分組成,請求報文的一般格式如下圖:

這裡寫圖片描述

1)請求行:由請求方法、URL和HTTP協議版本3個欄位組成,它們用空格分隔。例如,GET /index.html HTTP/1.1。HTTP協議的請求方法有GET、POST、HEAD、PUT、DELETE、OPTIONS、TRACE、CONNECT。而常見的有如下幾種:

  • GET:當客戶端要從伺服器中讀取文件時,當點選網頁上的連結或者通過在瀏覽器的位址列輸入網址來瀏覽網頁的,使用的都是GET方式。GET方法要求伺服器將URL定位的資源放在響應報文的資料部分,回送給客戶端。使用GET方法時,請求引數和對應的值附加在URL後面,利用一個問號(“?”)代表URL的結尾與請求引數的開始,傳遞引數長度受限制。例如,/index.jsp?id=100&op=bind。通過GET方式傳遞的資料直接放在在地址中,所以GET方式的請求一般不包含”請求內容”部分,請求資料以地址的形式表現在請求行。地址中”?”之後的部分就是通過GET傳送的請求資料,我們可以在位址列中清楚的看到,各個資料之間用”&”符號隔開。顯然這種方式不適合傳送私密資料。另外,由於不同的瀏覽器對地址的字元限制也有所不同,一般最多隻能識別1024個字元,所以如果需要傳送大量資料的時候,也不適合使用GET方式。如果資料是英文字母/數字,原樣傳送,如果是空格,轉換為+,如果是中文/其他字元,則直接把字串用BASE64加密,得出如: %E4%BD%A0%E5%A5%BD,其中%XX中的XX為該符號以16進製表示的ASCII

    • POST:允許客戶端給伺服器提供資訊較多。POST方法將請求引數封裝在HTTP請求資料中,以名稱/值的形式出現,可以傳輸大量資料,這樣POST方式對傳送的資料大小沒有限制,而且也不會顯示在URL中。POST方式請求行中不包含資料字串,這些資料儲存在“請求內容”部分,各資料之間也是使用”&“符號隔開。POST方式大多用於頁面的表單中。因為POST也能完成GET的功能,因此多數人在設計表單的時候一律都使用POST方式,其實這是一個誤區。GET方式也有自己的特點和優勢,我們應該根據不同的情況來選擇是使用GET還是使用POST。

    • HEAD:就像GET,只不過服務端接受到HEAD請求後只返回響應頭,而不會發送響應內容。當我們只需要檢視某個頁面的狀態的時候,使用HEAD是非常高效的,因為在傳輸的過程中省去了頁面內容

2)請求頭部:由關鍵字/值對組成,每行一對,關鍵字和值用英文冒號”:“分隔。請求頭部通知伺服器有關於客戶端請求的資訊,典型的請求頭有:

User-Agent:產生請求的瀏覽器型別。

Accept:客戶端可識別的內容型別列表。星號 “ * ” 用於按範圍將型別分組,用 “ / ” 指示可接受全部型別,用“ type/* ”指示可接受 type 型別的所有子型別。

Host:要請求的主機名,允許多個域名同處一個IP地址,即虛擬主機。

Accept-Language:客戶端可接受的自然語言。

Accept-Encoding:客戶端可接受的編碼壓縮格式。

Accept-Charset:可接受的應答的字符集。

connection:連線方式(close 或 keepalive)。

Cookie:儲存於客戶端擴充套件欄位,向同一域名的服務端傳送屬於該域的cookie

3)空行:最後一個請求頭部之後是一個空行,傳送回車符和換行符,通知伺服器以下不再有請求頭部

4)請求資料:請求資料不在GET方法中使用,而在POST方法中使用。POST方法適用於需要客戶填寫表單的場合。與請求資料相關的最常使用的請求頭部是Content-Type和Content-Length

5. 伺服器的永久重定向響應:

這裡寫圖片描述

伺服器給瀏覽器響應一個301永久重定向響應,這樣瀏覽器就會訪問“http://www.facebook.com/” 而非“http://facebook.com/”。為什麼伺服器一定要重定向而不是直接傳送使用者想看的網頁內容呢?其中一個原因跟搜尋引擎排名有關。如果一個頁面有兩個地址,就像http://www.igoro.com/http://igoro.com/,搜尋引擎會認為它們是兩個網站,結果造成每個搜尋連結都減少從而降低排名。而搜尋引擎知道301永久重定向是什麼意思,這樣就會把訪問帶www的和不帶www的地址歸到同一個網站排名下。還有就是用不同的地址會造成快取友好性變差,當一個頁面有好幾個名字時,它可能會在快取裡出現好幾次

一個http響應報文由狀態行<status-line>、響應頭部<headers>、空行<blank-line>
和響應資料<response-body>4個部分組成,響應報文的一般格式如下圖:

這裡寫圖片描述

1)狀態行: 由HTTP協議版本、伺服器返回的響應狀態碼和響應狀態碼的文字描述組成。

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

  1xx:資訊性狀態碼,表示伺服器已接收了客戶端請求,客戶端可繼續傳送請求。

       100 Continue

       101 Switching Protocols

   2xx:成功狀態碼,表示伺服器已成功接收到請求並進行處理。

       200 OK 表示客戶端請求成功

       204 No Content 成功,但不返回任何實體的主體部分

       206 Partial Content 成功執行了一個範圍(Range)請求

   3xx:重定向狀態碼,表示伺服器要求客戶端重定向。

       301 Moved Permanently 永久性重定向,響應報文的Location首部應該有該資源的新URL

       302 Found 臨時性重定向,響應報文的Location首部給出的URL用來臨時定位資源

       303 See Other 請求的資源存在著另一個URI,客戶端應使用GET方法定向獲取請求的資源

       304 Not Modified 客戶端傳送附帶條件的請求(請求首部中包含如If-Modified-Since等指定首部)時,服務端有可能返回304,此時,響應報文中不包含任何報文主體。

       307 Temporary Redirect 臨時重定向。與302 Found含義一樣。302禁止POST變換為GET,但實際使用時並不一定,307則更多瀏覽器可能會遵循這一標準,但也依賴於瀏覽器具體實現
   4xx:客戶端錯誤狀態碼,表示客戶端的請求有非法內容。

       400 Bad Request 表示客戶端請求有語法錯誤,不能被伺服器所理解

       401 Unauthonzed 表示請求未經授權,該狀態程式碼必須與 WWW-Authenticate 報頭域一起使用

       403 Forbidden 表示伺服器收到請求,但是拒絕提供服務,通常會在響應正文中給出不提供服務的原因

       404 Not Found 請求的資源不存在,例如,輸入了錯誤的URL

   5xx:伺服器錯誤狀態碼,表示伺服器未能正常處理客戶端的請求而出現意外錯誤。

       500 Internel Server Error 表示伺服器發生不可預期的錯誤,導致無法完成客戶端的請求

       503 Service Unavailable 表示伺服器當前不能夠處理客戶端的請求,在一段時間之後,伺服器可能會恢復正常

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

  Location:用於重定向接受者到一個新的位置。例如:客戶端所請求的頁面已不存在原先的位置,為了讓客戶端重定向到這個頁面新的位置,伺服器端可以發回Location響應報頭後使用重定向語句,讓客戶端去訪問新的域名所對應的伺服器上的資源

      Server:包含了伺服器用來處理請求的軟體資訊及其版本。它和 User-Agent 請求報頭域是相對應的,前者傳送伺服器端軟體的資訊,後者傳送客戶端軟體(瀏覽器)和作業系統的資訊

      Vary:指示不可快取的請求頭列表

      Connection:連線方式

   對於請求來說:close(告訴 WEB 伺服器或者代理伺服器,在完成本次請求的響應後,斷開連線,不等待本次連線的後續請求了)。keepalive(告訴WEB伺服器或者代理伺服器,在完成本次請求的響應後,保持連線,等待本次連線的後續請求);

   對於響應來說:close(連線已經關閉); keepalive(連線保持著,在等待本次連線的後續請求); Keep-Alive:如果瀏覽器請求保持連線,則該頭部表明希望WEB 伺服器保持連線多長時間(秒);例如:Keep-Alive:300;

     WWW-Authenticate:必須被包含在401 (未授權的)響應訊息中,這個報頭域和前面講到的Authorization 請求報頭域是相關的,當客戶端收到 401 響應訊息,就要決定是否請求伺服器對其進行驗證。如果要求伺服器對其進行驗證,就可以傳送一個包含了Authorization 報頭域的請求

3)空行:最後一個響應頭部之後是一個空行,傳送回車符和換行符,通知瀏覽器以下不再有響應頭部。

4)響應資料:伺服器返回給客戶端的文字資訊。

6. 瀏覽器跟蹤重定向地址

這裡寫圖片描述

現在瀏覽器知道了 “HTTP://www.facebook.com/”才是要訪問的正確地址,所以它會發送另一個http請求

7. 伺服器“處理”請求

伺服器接收到獲取請求,然後處理並返回一個響應。這表面上看起來是一個順向的任務,但其實這中間發生了很多有意思的東西,就像作者部落格這樣簡單的網站,何況像facebook那樣訪問量大的網站呢!web伺服器軟體(像IIS和阿帕奇)接收到HTTP請求,然後確定執行某一請求處理來處理它。請求處理就是一個能夠讀懂請求並且能生成HTML來進行響應的程式(像ASP.NET,PHP,RUBY…)

8. 伺服器發回一個HTML響應

9. 釋放 TCP 連線

若connection 模式為close,則伺服器主動關閉TCP 連線,客戶端被動關閉連線,釋放TCP 連線;若connection 模式為keepalive,則該連線會保持一段時間,在該時間內可以繼續接收請求

10. 客戶端瀏覽器解析HTML內容

客戶端將伺服器響應的 html 文字解析並顯示

11. 瀏覽器獲取嵌入在HTML中的物件

在瀏覽器顯示HTML時,它會注意到需要獲取其他地址內容的標籤。這時瀏覽器會發送一個獲取請求來重新獲得這些檔案。這些地址都要經歷一個和HTML讀取類似的過程。所以瀏覽器會在DNS中查詢這些域名,傳送請求,重定向等等…