- 前言
- 一、HTTP協議
- 1.1基本概念
- 1.2工作原理
- 二、請求過程
- 2.1域名解析
- 2.2TCP 連線
- 2.3傳送 HTTP 請求
- 2.4伺服器應答
- 2.5響應內容
- 2.6關閉連線
- 三、客戶端請求
- 3.1請求Header
- 3.2請求方法
- 3.3cookie 和 token
- 四、服務端響應
- 4.1demo 舉例
- 4.2返回內容
- 4.3返回狀態碼
- 五、文章小結
前言
最近筆者在實際專案開發中會頻繁涉及到服務之間的遠端呼叫、域名的配置和請求的轉發等與計算機網路相關的知識。
這些其實在讀本科和考研的時候都有學習過理論,但為了更透徹地掌握便於在工作中使用,我還是決定寫一篇文章來分享實際開發中是怎麼應用的。
下面將從 HTTP 協議的基本概念與簡介、完整的請求過程、客戶端的請求以及服務端的響應這四部分來展開,同時會使用實際的場景來加以分析,便於大家理解。
一、HTTP協議
1.1基本概念
HTTP 協議(Hyper Text Transfer Protocol)超文字傳輸協議,即傳輸文字、圖片、音訊、影片等超文字資料、是一種用於分散式、協作式和超媒體資訊系統的應用層協議。為了更快地處理大量事務,確保協議的可伸縮性,HTTP 協議被設計成了一種無狀態協議,不保留之前一切的請求或響應報文的資訊。HTTP 協議也是全球資訊網(WWW,World Wide Web)的資料通訊的基礎。
HTTP 是一個客戶端(使用者)和伺服器端(網站)請求和應答的標準,其定義了定義 Web 客戶端如何向 Web 伺服器請求 Web 頁面,以及伺服器如何把 Web 頁面響應給客戶端。
HTTP 協議中並沒有規定必須使用 TCP/IP 或其支援的層。事實上,HTTP 可以在任何網際網路協議上,或其他網路上實現。HTTP 假定其下層協議提供可靠的傳輸。因此,任何能夠提供這種保證的協議都可以被其使用,所以其在 TCP/IP 協議族使用 TCP 作為其傳輸層,而 UDP 是不可靠傳輸。
使用者透過使用各種工具(如網頁瀏覽器、網路爬蟲或者 Jmeter 等)作為客戶端,來發起一個 HTTP 請求到伺服器的指定埠(預設為80)。這個客戶端被稱為使用者代理程式(User Agent)。而接受並響應該 HTTP 請求的伺服器上會儲存著各種使用者需要的資源,比如 HTML 檔案和影像,這個被使用者請求的伺服器被稱為源伺服器(Origin Server)。
1.2工作原理
通常,由 HTTP 客戶端發起一個請求,建立一個到伺服器指定埠(預設是80埠)的 TCP 連線,HTTP伺服器則在那個埠監聽客戶端的請求。一旦收到請求,伺服器會向客戶端返回一個狀態,比如"HTTP/1.1 200 OK",以及響應請求而返回的內容,如檔案、錯誤訊息、或者其它資料等。
以下是 HTTP 協議工作流程的幾個關鍵步驟:
第一步:建立 TCP/IP 連線,客戶端與伺服器透過 Socket 三次握手進行連線
第二步:客戶端向服務端發起 HTTP 請求,如:POST/login.html http/1.1
第三步:客戶端傳送請求頭部、請求內容,最後會傳送一空白行,標示客戶端請求完畢
第四步:伺服器做出應答,表示對於客戶端請求的應答,如:HTTP/1.1 200 OK
第五步:伺服器向客戶端傳送響應頭部資訊,傳送一空白行,表示應答頭資訊傳送完畢,隨後以 Content-type 要求的資料格式,傳送響應正文給客戶端
第六步:服務端關閉 TCP 連線,如果伺服器或者客戶端的 Connection:keep-alive 則表示客戶端與伺服器端繼續儲存連線,在下次請求時可以繼續使用這次的連線
二、請求過程
下面對 1.2 小節中的幾個步驟做更為細緻的講解。
2.1域名解析
瀏覽器向 DNS 伺服器請求解析該 URL 中的域名所對應的 IP 地址,查詢過程依次如下:
-
瀏覽器快取
首先搜尋瀏覽器自身的 DNS 快取(快取的時間比較短,大概只有1分鐘,且只能容納1000條快取),看自身的快取中是否是有域名對應且未過期的條目。如果有,則域名解析到此結束。
-
作業系統快取
如果上一步沒有找到對應的條目,瀏覽器會搜尋作業系統自身的 DNS 快取,如果找到了沒有過期的對應條目,則停止搜尋,解析到此結束。檢視作業系統自身的 DNS 快取,以 Windows 系統為例,win + R 後輸入 cmd 命令提示行,輸入
ipconfig /displaydns
進行檢視。 -
hosts 檔案
如果上一步沒有找到對應條目,瀏覽器就會嘗試讀取作業系統本地的檔案,以 Windows 系統為例:
C:\Windows\System32\drivers\etc
內的 hosts 檔案。 -
DNS 伺服器
如果以上的三步都沒有找到對應條目,那麼瀏覽器就會向 DNS 伺服器請求進行域名解析。
更具體地說,瀏覽器發起一個 DNS 的系統呼叫,向本地配置的首選 DNS 伺服器(一般由運營商提供)發起域名解析請求。域名解析請求是透過 UDP 協議向DNS 的 53 埠發起請求,這個請求是遞迴的請求。也就是說,運營商的 DNS 伺服器必須得提供給我們該域名的公網 IP 地址。
2.2TCP 連線
根據 DNS 伺服器解析出的 IP 地址和預設埠號,與該伺服器進行 TCP 連線中 3 次握手的前兩次,來建立連線:
2.3傳送 HTTP 請求
即完成 TCP 的 3 次握手的第三次:
2.4伺服器應答
客戶端發起了請求,伺服器一定要有應答嗎?要回答這個問題,得知道 HTTP 響應的底層原理是基於 HTTP 協議的通訊機制,這個協議決定了:如果客戶端傳送的請求能準確到達伺服器,那麼伺服器必須會有響應並返回。
在本文的第四章,我會拿一個部署在 Linux 伺服器上的、基於Spring Boot 的 Java 程式來分析具體伺服器是怎麼做出響應的。
2.5響應內容
下面是訪問 https://mvnrepository.com/ 即 Maven 遠端中央倉庫時,呼叫其搜尋介面所產生的響應標頭內容:
2.6關閉連線
最後瀏覽器會關閉該 TCP 連線,瀏覽器利用自己內部的工作機制,把請求到的靜態資源和 HTML 程式碼進行渲染,呈現給使用者。
三、客戶端請求
下面其實是本文的重頭戲,會重點講解具體的 HTTP 請求是怎麼構建、傳送請求的。
3.1請求Header
一個 HTTP 請求報文由請求行(request line)、請求頭部(headers)、請求資料(request body)和空行(blank line)4個部分組成。
其中請求頭部(headers)為請求報文新增了一些附加資訊,由鍵值對組成,每行一對,名和值之間使用冒號分隔,如下圖是由 PostMan 呼叫所示:
常見的幾個請求頭釋義:
且我們還可以自定義 Header 如:Authorization 是認證資訊、Tenant-Code 是發起本次請求的租戶編碼。
注意:由於 HTTP 協議只規定 POST 提交的資料必須放在訊息主體(body)中,並沒有規定資料必須使用什麼編碼方式。服務端通常是根據請求頭中的 Content-Type 欄位來獲知請求中的訊息主體是用何種方式編碼,再對 body 進行解析。
常用的 Content-Type 編碼方式有:
- application/x-www-form-urlencoded 資料在傳送到伺服器之前,會將表單內的資料轉換為鍵值對,比如 username=admin&password=123456,並將所有字元都會進行 URL 轉碼;
- multipart/form-data 資料將被編碼為一條訊息以標籤為單元,用分隔符分開,既可以上傳鍵值對,也可以上傳檔案,通常用於上傳二進位制的檔案;
- application/json 用來告訴服務端訊息主體是序列化後的 JSON 字串,前端無法將表單的 enctype 屬性指定為 application/json,通常使用 Ajax 的方式傳送這種編碼形式的請求。
3.2請求方法
最常用的四種請求方法:GET、POST、PUT、DELETE。
3.3cookie 和 token
在瞭解 Session 和 Cookies 之前,我們還需要了解 HTTP 的一個特點,叫作無狀態。
HTTP 的無狀態是指 HTTP 協議對事務處理是沒有記憶能力的,也就是說伺服器不知道客戶端是什麼狀態。
這時兩個用於保持 HTTP 連線狀態的技術就出現了,它們分別是 Session 和 Cookie。
Session 在服務端,也就是網站的伺服器,用來儲存使用者的 Session 資訊。
Cookie 在客戶端,也可以理解為瀏覽器端有了 Cookie,瀏覽器在下次訪問網頁時會自動附帶上它傳送給伺服器,伺服器透過識別 Cookie 並鑑定出是哪個使用者,然後再判斷使用者是否是登入狀態,進而返回對應的響應。
四、服務端響應
4.1demo 舉例
這裡以一個基於 Spring Boot 的 Java 程式來舉例,@RequestMapping 是 Spring MVC 框架中的一個註解,它用於指示具體的 Controller 方法如何響應某個特定的請求。它可以用於將請求URL對映到控制器上,並可以指定不同的引數設定。
@RestController
@RequestMapping("/study")
public class StudyController {
@Resource
private StudyService studyService;
/**
* 新增
* @param studyDTO
* @return 是否成功
*/
@PostMapping("/add")
public BaseResponse<Boolean> addAwards(@RequestBody StudyDTO studyDTO) {
return ResultUtils.success(studyService.addStudy(studyDTO));
}
}
如果將這個應用部署在伺服器上,你想訪問到,那麼需要在瀏覽器中輸入:https://ip+port/服務名/study/add
我自己本地訪問則是:http://localhost:28089/initial/study/add
4.2返回內容
那麼 HTTP 返回的響應報文內容是什麼?主要包括以下3個部分:
-
響應狀態行(Status Line):包含HTTP協議版本、響應狀態碼和狀態訊息。例如,HTTP/1.1 200 OK 表示 HTTP 協議版本是1.1,響應狀態碼是 200,狀態訊息是 OK。這個在下一節會單獨拿出來講。
-
響應頭部(Headers):包含了一系列的鍵值對,用來描述響應的屬性和後設資料。常見的響應頭包括 Content-Type(指定響應的資料型別)、Content-Length(指定響應體的長度)等。HTTP 協議定義了許多標準的響應頭,不同的頭部欄位有不同的作用。
以下是一些常見的響應頭:
-
Content-Type:指定響應體的資料型別。例如,Content-Type: text/html 表示響應體是 HTML 文件。
-
Content-Length:指定響應體的長度,以位元組為單位。例如,Content-Length: 1024 表示響應體的長度是 1024 位元組。
-
Location:用於重定向客戶端到新的URL。例如,Location: http://example.com/new_page 會將客戶端重定向到 http://example.com/new_page。
-
Set-Cookie:用於設定 Cookie,可以在響應中向客戶端傳送 Cookie 資訊。
-
Cache-Control:控制響應的快取行為,包括快取的過期時間、驗證方式等。
-
Server:指定響應的伺服器資訊。例如,Server: Apache/2.4.38 表示響應是由 Apache 伺服器版本 2.4.38 生成的。
-
-
響應體(Body):包含了實際的響應資料,可以是HTML頁面、JSON資料、文字等。響應體的格式由Content-Type頭部欄位指定。
以下是一些常見的Content-Type值:
-
text/html:HTML 文件。
-
application/json:JSON 資料。
-
text/plain:純文字。
-
image/jpeg:JPEG影像。
-
application/xml:XML 資料。
-
4.3返回狀態碼
以下是一些常見的HTTP響應狀態碼:
五、文章小結
無論是前端還是後端,不論是科班還是非科班,也無論是開發、測試還是產品,瞭解和掌握 HTTP 請求的一些基本知識都是非常重要的。它是現代網際網路中不可或缺的一部分,為我們提供了高效、靈活、可靠的資料傳輸方式,為 Web 應用程式的開發和使用提供了強有力的支援。
今天的分享就到這裡,如有不足和錯誤,還請大家指正。或者你有其它想說的,也歡迎大家在評論區交流!
參考文件:
https://blog.csdn.net/u010804417/article/details/123638124
https://www.cnblogs.com/engeng/articles/5959335.html