網絡協議之 - HTTP

前言

關於HTTP的知識比較繁雜,也比較零散,於是想要通過這篇文章對常用知識點進行總結,一些知識點描述是從網上搜集而來,如有侵權,可以聯繫我進行修改。

提出問題

  1. Http的報文結構。
  2. Http request的幾種類型。
  3. Http的狀態碼含義。
  4. Http1.1和Http1.0的區別,以及緩存原理
  5. Http長連接keep-alive。
  6. Cookie與Session的作用於原理。
  7. 電腦上訪問一個網頁,整個過程是怎麼樣的:DNS、HTTP、TCP、OSPF、IP、ARP。

解答

1. Http的報文結構

http協議的請求報文和響應報文都是由以下4部分組成:

  1. 請求行
  2. 請求頭
  3. 空行 CR + LF,回車 + 換行
  4. 請求體

2. Http request的幾種類型

請求行

Request

格式:【方法 URL HTTP版本】 例如: GET /csrfToken HTTP/1.1

HTTP版本:目前有 HTTP/1.0、HTTP/1.1、HTTP/2.0 版本,其中 HTTP1.1 版本使用較廣泛

方法 說明 支持HTTP協議版本
GET 獲取資源 1.0 、1.1
POST 傳輸實體主體 1.0、1.1
PUT 傳輸文件 1.0、1.1
HEAD 獲得報文首部 1.0、1.1
DELETE 刪除資源 1.0、1.1
OPTIONS 詢問支持的方法 1.1
TRACE 追蹤路徑 1.1
CONNECT 要求用隧道協議連接代理 1.1
LINK 建立和資源之間的聯繫 1.0
UNLINK 斷開連接關係 1.0

Response

格式:【HTTP版本 狀態碼 描述】 例如: HTTP/1.1 200 OKHTTP/1.1 404 NOT FOUND

類別 原因短語
1xx Informational(信息性狀態碼) 接收的請求正在處理
2xx Success(成功狀態碼) 請求正常處理完畢
3xx Redirection(重定向狀態碼) 需要進行附加操作以完成請求
4xx Client Error(客戶端錯誤狀態碼) 服務器無法處理請求
5xx Server Error(服務器錯誤狀態碼) 服務器處理請求出錯

3. Http的狀態碼含義

常用狀態碼
  • 200:OK,請求被正常處理
  • 204:No Content,請求被受理但沒有資源可以返回,返回204響應,瀏覽器顯示的頁面不發生更新
  • 206:Partial Content,客戶端進行範圍請求,服務器成功執行了這部分的GET請求,響應報文中包含由Content-Range指定範圍的實體內容
  • 301:Moved Permanently,永久性重定向,比如訪問http://test.zhixue.com/zbptadmin,服務器會返回301,response的headers中會包含一個字段:Location: http://test.zhixue.com/zbptadmin/,瀏覽器會按照這個地址重新請求,並且如果用戶保存了書籤,瀏覽器會自動按照Location更新書籤
  • 302:Found,臨時性重定向,和301類似,但是瀏覽器不會更新書籤
  • 303:See Other,和302類似,但303明確表示客戶端應該使用GET方法獲取Location資源
  • 備註:當301,302,303響應狀態碼返回時,幾乎所有的瀏覽器都會把POST改成GET,並刪除請求報文內的主體,之後請求會自動再次發送。301,302標準是禁止將POST方法改成GET方法的,但實際使用時瀏覽器廠商都會這麼做。
  • 304:Not Modified,發送附帶條件的請求時,(附帶條件的請求是指採用GET方法的請求報文中包含If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since中任一首部),條件不滿足返回304,可直接使用客戶端緩存,與重定向無關
  • 307:Temporary Redirect,臨時重定向,與302類似,只是強制要求使用POST方法
  • 400:Bad Request,請求報文中存在語法錯誤,服務器無法識別
  • 401:Unauthorized,請求需要認證
  • 403:Forbidden,請求對應的資源禁止被訪問
  • 404:Not Found,服務器無法找到對應資源
  • 500:Internal Server Error,服務器內部錯誤
  • 503:Service Unavailable,服務器正忙

常見HTTP首部字段

通用首部字段(請求報文與響應報文都會使用的首部字段)

  • Date:創建報文的時間
  • Connection:連接的管理
  • Cache-Control:緩存的控制
  • Transfer-Encoding:報文主題的傳輸編碼方式

請求首部字段(請求報文會使用的首部字段)

  • Host:請求資源所在的服務器
  • Accept:可處理的媒體類型
  • Accept-Charset:可接收的字符集
  • Accept-Encoding:可接收的內容編碼
  • Accept-Language:可接收的自然語言

響應首部字段(響應報文會使用的首部字段)

  • Accept-Range:可接收的字節範圍
  • Location:讓客戶端重定向到的URI
  • Server:HTTP服務器的安裝信息

實體首部字段(請求報文與響應報文的實體部分使用的首部字段)

  • Allow:資源可支持的HTTP方法
  • Content-Type:實體主類的類型
  • Content-Encoding:實體主體適用的編碼方式
  • Content-Language:實體主體的自然語言
  • Content-Length:實體主體的字節數
  • Content-Range:實體主體的位置範圍,一般用於發出部分請求時使用

4. HTTP1.0、HTTP1.1、HTTP2.0區別

HTTP1.0 和 HTTP1.1 主要區別

  1. 長連接

    • HTTP1.0需要使用keep-alive參數告知服務器要建立一個長連接,而HTTP1.1默認支持長連接
    • HTTP是基於TCP/IP協議的,創建一個TCP連接是需要經過三次握手的,有一定的開銷,如果每次通訊都要重新建立連接的話,對性能有影響。因此最好能維持一個長連接,可以用這個長連接來發送多個請求
  2. 節約帶寬

    • HTTP1.1支持只發送header信息,也就是HTTP的HEAD Method,如果服務器認爲客戶端有權限請求服務器,則返回100,否則返回401。客戶端如果接收到100,纔開始把請求體body發送到服務器。
    • 這樣,當服務器返回401的時候,客戶端就可以不用發送請求體了,節約了帶寬
    • HTTP1.1支持分塊傳輸,比如206狀態碼,由Content-Range指定傳輸內容,這是支持文件斷點續傳的基礎。
  3. HOST域

    • 現在一臺服務器上可以有多個虛擬主機,這些虛擬站點可以共享同一個ip和端口,HTTP1.0是沒有host域的,HTTP1.1才支持這個參數

HTTP1.1 和 HTTP2.0的區別

  1. 多路複用

    • HTTP2.0使用了多路複用的技術,做到同一個連接併發處理多個請求,而且併發請求的數量比HTTP1.1大了好幾個數量級

      • 當然HTTP1.1也可以多建立幾個TCP連接,來支持處理更多併發的請求,但是創建TCP連接本身也是有開銷的
      • TCP連接有一個預熱和保護的過程,先檢查數據是否傳送成功,一旦成功過,則慢慢加大傳輸速度。因此對應瞬時併發的連接,服務器的響應就會變慢。所以最好能使用一個建立的連接,並且這個連接可以支持瞬時併發的請求
      • HTTP/1.1,若干個請求排隊串行化單線程處理,後面的請求等待前面請求的返回才能獲得執行機會,一旦有某個請求超時,後續請求只能被阻塞,也就是人們常說的線頭阻塞
      • HTTP/2.0,多個請求可同時在一個連接上並行執行,某個任務耗時嚴重,不會影響到其他連接的正常執行
  2. 數據壓縮

    • HTTP1.1不支持header數據的壓縮,HTTP2.0使用HPACK算法對header的數據進行壓縮,這樣數據體積小了,在網絡上傳輸就會更快
  3. 服務器推送

    • 當我們對HTTP2.0的web server請求數據的時候,服務器會順便把一些客戶端需要的資源一起推送到客戶端,免得客戶端再次創建連接發送請求到服務器獲取。這種方式非常適合加載靜態資源。
    • 服務器推送的這些資源其實存在客戶端的某個地方,客戶端直接從本地加載這些資源就可以了,不用走網絡,速度自然快很多。

HTTP緩存

緩存分類

  • 強緩存

瀏覽器在加載資源時,先根據這個資源的一些http header判斷它是否命中強緩存,如果命中,瀏覽器直接從自己的緩存中讀取資源,不會發請求到服務器,此時狀態碼是200,但是看Size項是from memory cache或from disk cache

  • 協商緩存
  • 當強緩存沒有命中時,瀏覽器一定會發送一個請求到服務器,通過服務器端依據資源的另外一些http header驗證這個資源是否命中協商緩存,如果命中,服務器會將這個請求返回304,但是不會返回這個資源的數據,而是告訴客戶端可以直接從緩存中加載這個資源,於是瀏覽器就又會從自己的緩存中去加載這個資源;如果沒有命中,則將資源返回客戶端,狀態爲200,瀏覽器同時依據response header中的相關項更新本地緩存數據

from memory cache 和 from disk cache

區別
  1. from memory cache 是從內存中讀取緩存資源,很快,關閉瀏覽器後,內存中的資源就消失了
  2. from disk cache 是從磁盤中讀取緩存資源,要比 from memory cache 慢,但是持久化,關閉瀏覽器後仍然存在
哪些資源存在memory,哪些資源存在disk

看了一些文章,大部分觀點是說:

  1. 資源在disk和memory中都會存
  2. 當關閉瀏覽器,再打開那個頁面的時候,從disk cache中獲取緩存資源,同時將緩存資源存在了內存中,當再次刷新頁面的時候,就從memory cache中讀取,因爲這樣會更快一些
  3. 我自己試了一些頁面,再次刷新還是有的from disk cache,有的from memory cache,所以這個持保留觀點
  4. 還有的文章說css文件存在disk中,js等腳本存在memory中,個人認爲這個不太靠譜,因爲memory中的緩存在關閉瀏覽器就消失了,如果js只存在memory,就起不到緩存的作用了

強緩存相關http header

  • Expires

Expires的值是服務端返回的到期時間,用GMT格式的字符串表示,如:Expires: Thu, 31 Dec 2016 23:55:55 GMT。即下一次請求時,請求時間小於服務器返回的到期時間,直接使用緩存數據。不過Expires是HTTP1.0的東西,現在瀏覽器默認使用HTTP1.1,所以它的作用基本忽略。另一個問題是,到期時間是由服務器生成的,但是客戶端時間可能和服務器時間有偏差,這就會導致緩存命中的誤差。所以HTTP1.1的版本中,使用Cache-Control替代。

  • Cache-Control

Cache-Control是最重要的規則。常見的取值有:

- ```private```:客戶端可以緩存
- ```public```:客戶端和代理服務器都可以緩存
- ```max-age=xxx```:緩存的內容將在xxx秒後失效,單位是秒
- ```no-cache```:需要使用**協商緩存**來驗證緩存數據
- ```no-store```:不緩存

協商緩存相關http header

第1組:Last-Modified/If-Modified—Since

  • Last-Modified:第一次請求資源時,服務器返回的http header,告訴瀏覽器資源的最後修改時間,爲GMT格式,如Last-Modified: Thu, 24 Jan 2017 23:55:55 GMT
  • If-Modified-Since:再次請求服務器資源時,瀏覽器設置在請求header中,值 爲該資源第一次請求時服務器設置的Last-Modified`值,如`If-Modified-Since: Thu, 24 Jan 2017 23:55:55 GMT`,服務器收到請求後發現request header中有`If-Modified-Since`,則與被請求資源的最後修改時間進行比對。若資源的最後修改時間大於`If-Modified-Since`,說明資源又被改動過,則返回資源內容,狀態碼200,同時瀏覽器依據相應response header更新緩存資源;若資源的最後修改時間小於或等於`If-Modified-Since``,說明資源無新修改,則返回狀態碼304,但是不返回資源,告知瀏覽器繼續使用所保存的cache

第2組:Etag/If-None-Match

  • Etag:服務器響應請求時,告訴瀏覽器當前資源在服務器的唯一標識(生成規則由服務器確定),如Etag: W/"5886c231-8d9"
  • If-None-Match:再次請求服務器時,通過此字段告知服務器該資源的唯一標識,如If-None-Match: W/"5886c231-8d9",服務器收到請求後發現request header中有If-None-Match,則與被請求資源的唯一標識進行比對,若不同,說明資源又被改動過,則返回資源內容,狀態碼200,同時瀏覽器依據相應response header更新緩存資源;若相同,則說明資源無更改,返回304,告知瀏覽器繼續使用所保存的緩存資源

總結

  1. 先執行強緩存策略,服務器通知瀏覽器一個緩存有效時間,在有效時間內,下次請求時直接使用緩存,不發起http請求,緩存從from memory cache或from disk cache中讀取,若超過了有效時間,則執行協商緩存策略
  2. 對於協商緩存,將緩存信息中的Etag和Last-Modified的值通過If-None-Match和If-Modified-Since發送給服務器,由服務器進行校驗,若資源無更改,返回304,瀏覽器繼續使用緩存,若資源被更改,則返回資源,狀態碼200,同時瀏覽器更新緩存

流程圖

瀏覽器第一次請求:

瀏覽器第二次請求:

5. Http長連接keep-alive

三個概念

  1. 短連接

所謂短連接,就是每次請求一個資源就建立連接,請求完成後立馬關閉。每次請求都經過“創建TCP連接 -> 請求資源 -> 響應資源 -> 釋放連接”。

  1. 長連接

所謂長連接(persistent connection),就是隻建立一次TCP連接,多次HTTP請求都複用該連接。

  1. 並行連接

所謂並行連接(multiple connection),其實就是併發的短連接。

keep-alive

在HTTP/1.0裏,爲了實現client到web-server能支持長連接,必須在HTTP請求頭裏顯式指定Connection: keep-alive

在HTTP/1.1裏,就默認開啓了keep-alive,要關閉keep-alive必須在HTTP請求頭裏顯式指定Connection: close

現在大多數瀏覽器都默認是使用HTTP/1.1,所以keep-alive都是默認打開的。一旦client和server達成協議,那麼長連接就建立好了。

keepalive_timeout

Httpd守護進程,一般都提供了keep-alive timeout時間設置參數。比如nginx的keepalive_timeout,和Apache的KeepAliveTimeout。這個keepalive_timout時間值意味着:一個http產生的tcp連接在傳送完最後一個響應後,還需要hold住keepalive_timeout秒後,纔開始關閉這個連接。Nginx配置中的keepalive_timeout默認爲75s,

6. cookie與Session

這個重點在於理解,這裏就不贅述了。

7. 網頁經歷了什麼

這個東西很多,後面會專門寫一篇文章來進行說明。

參考文章:

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