最近筆者在實際項目開發中會頻繁涉及到服務之間的遠程調用、功能變數名稱的配置和請求的轉發等與電腦網路相關的知識。 這些其實在讀本科和考研的時候都有學習過理論,但為了更透徹地掌握便於在工作中使用,我還是決定寫一篇文章來分享實際開發中是怎麼應用的。 ...
目錄
前言
最近筆者在實際項目開發中會頻繁涉及到服務之間的遠程調用、功能變數名稱的配置和請求的轉發等與電腦網路相關的知識。
這些其實在讀本科和考研的時候都有學習過理論,但為了更透徹地掌握便於在工作中使用,我還是決定寫一篇文章來分享實際開發中是怎麼應用的。
下麵將從 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