互聯網基礎協議 – HTTP

  • 2019 年 10 月 30 日
  • 筆記

HTTP

HTTP的簡介

超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最為廣泛的一種網路協議。所有的WWW文件都必須遵守這個標準。

HTTP是一個基於TCP/IP通訊協議來傳遞數據(HTML 文件, 圖片文件, 查詢結果等)。

HTTP是一個屬於應用層的面向對象的協議,由於其簡捷、快速的方式,適用於分散式超媒體資訊系統。它於1990年提出,經過幾年的使用與發展,得到不斷地完善和擴展。目前在WWW中使用的是HTTP/1.0的第六版,HTTP/1.1的規範化工作正在進行之中,而且HTTP-NG(Next Generation of HTTP)的建議已經提出。

HTTP協議工作於客戶端-服務端架構為上。瀏覽器作為HTTP客戶端通過URL向HTTP服務端即WEB伺服器發送所有請求。Web伺服器根據接收到的請求後,向客戶端發送響應資訊。

HTTP的特點

  1. 支援客戶/伺服器模式。
  2. 簡單快速:客戶向伺服器請求服務時,只需傳送請求方法和路徑。請求方法常用的有GET、HEAD、POST。每種方法規定了客戶與伺服器聯繫的類型不同。
    由於HTTP協議簡單,使得HTTP伺服器的程式規模小,因而通訊速度很快。
  3. 靈活:HTTP允許傳輸任意類型的數據對象。正在傳輸的類型由Content-Type加以標記。
  4. 無連接:無連接的含義是限制每次連接只處理一個請求。伺服器處理完客戶的請求,並收到客戶的應答後,即斷開連接。採用這種方式可以節省傳輸時間。
  5. 無狀態:HTTP協議是無狀態協議。無狀態是指協議對於事務處理沒有記憶能力。缺少狀態意味著如果後續處理需要前面的資訊,則它必須重傳,這樣可能導致每次連接傳送的數據量增大。另一方面,在伺服器不需要先前資訊時它的應答就較快。

HTTP的URL(UniformResourceLocator)

URL格式:

 http://host[:port][abs_path]

http表示要通過HTTP協議來定位網路資源。
host表示合法的Internet主機域名或IP地址(以點分十進位格式表示)。
port用於指定一個埠號,擁有被請求資源的伺服器主機監聽該埠的TCP連接。
如果port是空,則使用預設的埠80。當伺服器的埠不是80的時候,需要顯式指定埠號。
abs_path指定請求資源的URI(Uniform Resource Identifier,統一資源定位符),如果URL中沒有給出abs_path,那麼當它作為請求URI時,必須以「/」的形式給出。通常這個工作瀏覽器就幫我們完成了。

HTTP的請求消息Request

消息格式:
HTTP 消息格式

先來看下HTTP的請求消息頭:

  • Accept: text/html,image/* 【瀏覽器告訴伺服器,它支援的數據類型】
  • Accept-Charset: ISO-8859-1 【瀏覽器告訴伺服器,它支援哪種字符集】
  • Accept-Encoding: gzip,compress 【瀏覽器告訴伺服器,它支援的壓縮格式】
  • Accept-Language: en-us,zh-cn 【瀏覽器告訴伺服器,它的語言環境】
  • Host: www.codingme.net:80【瀏覽器告訴伺服器,它的想訪問哪台主機】
  • If-Modified-Since: Tue, 11 Jul 2000 18:23:51 GMT【瀏覽器告訴伺服器,快取數據的時間】
  • Referer: http://www.codingme.net/index.jsp【瀏覽器告訴伺服器,客戶機是從那個頁面來的—反盜鏈
  • 8.User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)【瀏覽器告訴伺服器,瀏覽器的內核是什麼】
  • Cookie【瀏覽器告訴伺服器,帶來的Cookie是什麼】
  • Connection: close/Keep-Alive 【瀏覽器告訴伺服器,請求完後是斷開鏈接還是保持鏈接】
  • Date: Tue, 11 Jul 2000 18:23:51 GMT【瀏覽器告訴伺服器,請求的時間

使用Chrome請求網址進行觀察:

Chrome請求資訊

Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8  Accept-Encoding:gzip, deflate  Accept-Language:zh-CN,zh;q=0.8  Connection:keep-alive  Cookie:JSESSIONID=2A40A51EDDE663C840A2D03B7587D660; Hm_lvt_1b51c3ea9a3e7b1a2bc55df97ab4efd3=1500964170,1500976171,1500994669,1501056813; Hm_lpvt_1b51c3ea9a3e7b1a2bc55df97ab4efd3=1501056816  Host:blog.codingme.net  Upgrade-Insecure-Requests:1  User-Agent:Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3080.5 Safari/537.36

HTTP的響應消息Response

一個完整的HTTP響應應該包含四個部分:

  1. 一個狀態行【用於描述伺服器對請求的處理結果。】
  2. 多個消息頭【用於描述伺服器的基本資訊,以及數據的描述,伺服器通過這些數據的描述資訊,可以通知客戶端如何處理等一會兒它回送的數據】
  3. 一個空行
  4. 實體內容【伺服器向客戶端回送的數據】

響應消息頭的詳細解釋:

  • Location: http://www.codingme.net/index.jsp 【伺服器告訴瀏覽器要跳轉到哪個頁面】
  • Server:apache tomcat【伺服器告訴瀏覽器,伺服器的型號是什麼】
  • Content-Encoding: gzip 【伺服器告訴瀏覽器數據壓縮的格式】
  • Content-Length: 80 【伺服器告訴瀏覽器回送數據的長度】
  • Content-Language: zh-cn 【伺服器告訴瀏覽器,伺服器的語言環境】
  • Content-Type: text/html; charset=GB2312 【伺服器告訴瀏覽器,回送數據的類型】
  • Last-Modified: Tue, 11 Jul 2000 18:23:51 GMT【伺服器告訴瀏覽器該資源上次更新時間】
  • Refresh: 1;url=http://www.codingme.net【伺服器告訴瀏覽器要定時刷新
  • Content-Disposition: attachment; filename=aaa.zip【伺服器告訴瀏覽器以下載方式打開數據】
  • Transfer-Encoding: chunked 【伺服器告訴瀏覽器數據以分塊方式回送】
  • Set-Cookie:SS=Q0=5Lb_nQ; path=/search【伺服器告訴瀏覽器要保存Cookie】
  • Expires: -1【伺服器告訴瀏覽器不要設置快取】
  • Cache-Control: no-cache 【伺服器告訴瀏覽器不要設置快取】
  • Pragma: no-cache 【伺服器告訴瀏覽器不要設置快取】
  • Connection: close/Keep-Alive 【伺服器告訴瀏覽器連接方式】
  • Date: Tue, 11 Jul 2000 18:23:51 GMT【伺服器告訴瀏覽器回送數據的時間】

Chrome請求網址http://bing.codingme.net 抓包展示;
Chrome 請求資訊

HTTP的狀態碼

狀態程式碼有三位數字組成,第一個數字定義了響應的類別,共分五種類別:

1xx:指示資訊–表示請求已接收,繼續處理

2xx:成功–表示請求已被成功接收、理解、接受

3xx:重定向–要完成請求必須進行更進一步的操作

4xx:客戶端錯誤–請求有語法錯誤或請求無法實現

5xx:伺服器端錯誤–伺服器未能實現合法的請求

常見狀態碼:

  • 200 OK //客戶端請求成功
  • 400 Bad Request //客戶端請求有語法錯誤,不能被伺服器所理解
  • 401 Unauthorized //請求未經授權,這個狀態程式碼必須和WWW-Authenticate報頭域一起使用
  • 403 Forbidden //伺服器收到請求,但是拒絕提供服務
  • 404 Not Found //請求資源不存在,eg:輸入了錯誤的URL
  • 500 Internal Server Error //伺服器發生不可預期的錯誤
  • 503 Server Unavailable //伺服器當前不能處理客戶端的請求,一段時間後可能恢復正常

詳情可以查看更多狀態碼

HTTP的請求方法(動作)

HTTP協議中定義了8種方法來表明不同的動作

  1. OPTIONS
    返回伺服器針對特定資源所支援的HTTP請求方法,也可以利用向web伺服器發送『*』的請求來測試伺服器的功能性。

  2. HEAD
    向伺服器索與GET請求相一致的響應,只不過響應體將不會被返回。這一方法可以再不必傳輸整個響應內容的情況下,就可以獲取包含在響應小消息頭中的元資訊。

  3. GET
    向特定的資源發出請求。注意:GET方法不應當被用於產生「副作用」的操作中,例如在Web Application中,其中一個原因是GET可能會被網路蜘蛛等隨意訪問。
    Loadrunner中對應get請求函數:web_link和web_url.

  4. POST
    向指定資源提交數據進行處理請求(例如提交表單或者上傳文件)。數據被包含在請求體中。POST請求可能會導致新的資源的建立和/或已有資源的修改。 Loadrunner中對應POST請求函數:web_submit_data,web_submit_form.

  5. PUT
    向指定資源位置上傳其最新內容。

  6. DELETE
    請求伺服器刪除Request-URL所標識的資源。

  7. TRACE
    回顯伺服器收到的請求,主要用於測試或診斷。

  8. CONNECT
    HTTP/1.1協議中預留給能夠將連接改為管道方式的代理伺服器。

TCP的三次握手

HTTP使用TCP進行輸出傳輸,在建立TCP連接時會進行三次握手。

所謂三次握手(Three-Way Handshake)即建立TCP連接,就是指建立一個TCP連接時,需要客戶端和服務端總共發送3個包以確認連接的建立。在socket編程中,這一過程由客戶端執行connect來觸發,整個流程如下圖所示:

TCP 三次握手

  1. 建立連接時,客戶端發送SYN包(SYN=i)到伺服器,並進入到SYN-SEND狀態,等待伺服器確認
  2. 伺服器收到SYN包,必須確認客戶的SYN(ack=i+1),同時自己也發送一個SYN包(SYN=k),即SYN+ACK包,此時伺服器進入SYN-RECV狀態
  3. 客戶端收到伺服器的SYN+ACK包,向伺服器發送確認報ACK(ack=k+1),此包發送完畢,客戶端和伺服器進入ESTABLISHED狀態,完成三次握手,客戶端與伺服器開始傳送數據。

HTTP協議工作流程

以訪問網站為例,在回車之後所發生的動作:

  1. 瀏覽器向 DNS 伺服器請求解析該 URL 中的域名所對應的 IP 地址;
  2. 解析出 IP 地址後,根據該 IP 地址和默認埠 80,和伺服器建立TCP連接;
  3. 瀏覽器發出讀取文件(URL 中域名後面部分對應的文件)的HTTP 請求,該請求報文作為 TCP 三次握手的第三個報文的數據發送給伺服器;
  4. 伺服器對瀏覽器請求作出響應,並把對應的 html 文本發送給瀏覽器;
  5. 釋放 TCP連接;
  6. 瀏覽器將該 html 文本並顯示內容;  

GET請求和POST請求的區別

使用Chrome瀏覽器進行GET請求測試:

Request URL:http://localhost:8888/01-web_servlet/loginServlet?username=zxy&password=123
Request Method:GET
Status Code:200
Remote Address:[::1]:8888
Referrer Policy:no-referrer-when-downgrade

使用Chrome瀏覽器進行POST請求測試:

Request URL:http://localhost:8888/01-web_servlet/loginServlet
Request Method:POST
Status Code:200
Remote Address:[::1]:8888
Referrer Policy:no-referrer-when-downgrade

由測試可以看到GET和POST最明顯的區別就是

  1. GET攜帶的參數傳遞置於URL中以?分割URL和傳輸數據,多個參數用&連接,如果數據是英文字母/數字,原樣發送,如果是空格,轉換為+,如果是中文/其他字元,則直接把字元串用BASE64加密,不安全
    POST把提交的數據放置在是HTTP包的包體中。因此,GET提交的數據會在地址欄中顯示出來,而POST提交,地址欄不會改變
  2. 網上搜索得到如下區別
  3. GET提交的數據大小有限制(因為瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制.
  4. GET方式需要使用Request.QueryString來取得變數的值,而POST方式通過Request.Form來獲取變數的值。
  5. GET方式提交數據,會帶來安全問題,比如一個登錄頁面,通過GET方式提交數據時,用戶名和密碼將出現在URL上,如果頁面可以被快取或者其他人可以訪問這台機器,就可以從歷史記錄獲得該用戶的帳號和密碼.
  6. GET產生一個TCP數據包;POST產生兩個TCP數據包。

<完>

本文作者:未讀程式碼
我的微信:wn8398
個人主頁:www.codingme.net
本篇文章是部落客原創文章,歡迎轉載,轉載時在明顯位置註明原文鏈接即可。
關注公眾號回復資源可以獲取Java 核心知識整理&面試資料。