應用層協議 HTTP
前置知識
- 我們上網的所有行為都是在做IO,(我的數據給別人,別人的數據給我)
- 圖片。視頻,音頻,文本等等,都是資源
- 答復前需要先確認我要的資源在哪臺服務器上(網絡IP),在確定資源在什么路徑上(服務器資源路徑)
HTTP 協議
雖然我們說,應用層協議是我們程序猿自己定的。但實際上,已經有大佬們定義了一些現成的,又非常好用的應用層協議,供我們直接參考使用。HTTP
(超文本傳輸協議)就是其中之一。
在互聯網世界中,HTTP
(HyperText Transfer Protocol,超文本傳輸協議)是一個至關重要的協議。它定義了客戶端(如瀏覽器)與服務器之間如何通信,以交換或傳輸超文本(如HTML文檔)。
HTTP協議是客戶端與服務器之間通信的基礎。客戶端通過HTTP協議向服務器發送請求,服務器收到請求后處理并返回響應。HTTP協議是一個無連接、無狀態的協議,即每次請求都需要建立新的連接,且服務器不會保存客戶端的狀態信息。
認識URL
平時我們俗稱的“網址”其實就是說的URL
?
右側為傳參- URL中,
/
不一定是根目錄,其實叫做web根目錄,兩者不一定是同一個 - 成熟的應用層協議,往往是和端口號強相關的。
urlencode和urldecode
像 / 、? 、: 等這樣的字符,已經被url當做特殊意義理解了。因此這些字符不能隨意出現。比如,某個參數中需要帶有這些特殊字符,就必須先對特殊字符進行轉義。
轉義的規則如下:
將需要轉碼的字符轉為16進制,然后從右到左,取4位(不足4位直接處理),每2位做一位,前面加上%,編碼成%XY格式
例如:“+” 被轉義成了 “%2B”
urldecode就是urlencode的逆過程;4
urlencode工具
HTTP協議請求與響應格式
HTTP請求
POST http://job.xjtu.edu.cn/companyLogin.do HTTP/1.1
Host: job.xjtu.edu.cn
Connection: keep - alive
Content - Length: 36
Cache - Control: max - age=0
Origin: http://job.xjtu.edu.cn
Upgrade - Insecure - Requests: 1
Content - Type: application/x - www - form - urlencoded
User - Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Referer: http://job.xjtu.edu.cn/companyLogin.do
Accept - Encoding: gzip, deflate
Accept - Language: zh - CN,zh;q=0.8
Cookie: JSESSIONID=D628a75845a74D29D91DB47A461E4FC;
Hm_lvt_783e83ce0ee350e23a9d389df580f658=1504963710,1506661798;
Hm_lpvt_783e83ce0ee350e23a9d389df580f658=1506661802
username=hgtz2222&password=222222222
- 首行:[方法] + [url] + [版本]
Header
(請求報頭):請求的屬性,冒號分割的鍵值對;每組屬性之間使用\n分隔;遇到空行表示Header部分結束Body
(請求正文):空行后面的內容都是Body。Body允許為空字符串。如果Body存在,則在Header中會有一個Content - Length屬性來標識Body的長度;
注意:http協議自己做序列化和反序列化,偏底層,不想依賴任何庫。
HTTP響應
HTTP/1.1 200 OK
Server: YX1k waf
Content - Type: text/html; charset=UTF - 8
Content - Language: zh - CN
Transfer - Encoding: chunked
Date: Fri, 29 Sep 2017 05:10:13 GMT
<!DOCTYPE html>
<html>
<head>
<title>西安交通大學就業網</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<link href="/shortcut icon/css/href/main.css" rel="stylesheet" media="screen" />
<link href="/renovation/css/font-awesome.css" rel="stylesheet" media="screen" />
<link href="/renovation/css/font-default.css" rel="stylesheet" media="screen" />
<script type="text/javascript" src="/renovation/js/jquery1.7.1.min.js"></script>
<script type="text/javascript" src="/renovation/js/main.js"></script><!--main-->
<link href="/style/warmipsstyle.css" rel="stylesheet" type="text/css">
</head>
- 首行:[版本號] + [狀態碼] + [狀態碼解釋]
- Header:請求的屬性,冒號分割的鍵值對;每組屬性之間使用\n分隔;遇到空行表示Header部分結束
- Body:空行后面的內容都是Body。Body允許為空字符串。如果Body存在,則在Header中會有一個Content - Length屬性來標識Body的長度;如果服務器返回了一個html頁面,那么html頁面內容就是在body中。
HTTP的方法
方法 | 說明 | 支持的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.0、1.1 |
TRACE | 追蹤路徑 | 1.1 |
CONNECT | 要求用隧道協議連接代理 | 1.1 |
LINK | 建立和資源之間的聯系 | 1.0 |
UNLINK | 斷開連接關系 | 1.0 |
其中最常用的就是GET
方法和POST
方法。
- GET方法(重點)
- 用途:用于請求URL指定的資源。
- 示例:GET /index.html HTTP/1.1
- 特性:指定資源經服務器端解析后返回響應內容。
- form表單:https://www.runoob.com/html/html-forms.html
- C++代碼示例:
std::string GetFileContentHelper(const std::string &path)
{// 一份簡單的讀二進制文件的代碼std::ifstream in(path, std::ios::binary);if (!in.is_open())return "";in.seekg(0, in.end);int filesize = in.tellg();in.seekg(0, in.beg);std::string content;content.resize(filesize);in.read((char *)content.c_str(), filesize);// std::vector<char> content(filesize);// in.read(content.data(), filesize);in.close();return content;
}
- POST方法(重點)
- 用途:用于傳輸實體的主體,通常用于提交表單數據。
- 示例:POST /submit.cgi HTTP/1.1
- 特性:可以發送大量的數據給服務器,并且數據包含在請求體中。
- form表單:https://www.runoob.com/html/html-forms.html
- 說明:要通過歷史寫的http服務器,驗證POST方法,這里需要了解一下FORM表單的問題。
GET
通常獲取網頁內容,傳參通過URL(拼接到URL的后面)
POST
通常用來上傳數據,傳參通過body(正文)
- PUT方法(不常用)
- 用途:用于傳輸文件,將請求主體中的文件保存到請求URL指定的位置。
- 示例:PUT /example.html HTTP/1.1
- 特性:不太常用,但在某些情況下,如RESTful API中,用于更新資源。
- HEAD方法
- 用途:與GET方法類似,但不返回報文主體部分,僅返回響應頭。
- 示例:HEAD /index.html HTTP/1.1
- 特性:用于確認URL的有效性及資源更新的日期時間等。
- C++示例:
// curl -i 顯示
$ curl -i www.baidu.com
HTTP/1.1 200 OK
Accept - Ranges: bytes
Cache - Control: private, no - cache, no - store, proxy - revalidate, no - transform
Connection: keep - alive
Content - Length: 2381
Content - Type: text/html
Date: Sun, 16 Jun 2024 08:38:04 GMT
Etag: "588604dc - 94d"
Last - Modified: Mon, 23 Jan 2017 13:27:56 GMT
Pragma: no - cache
Server: bfe/1.0.8.18
Set - Cookie: BDORZ=27315; max - age=86400; domain=.baidu.com; path=/
<!DOCTYPE html>
...// 使用head方法,只會返回響應頭
$ curl --head www.baidu.com
HTTP/1.1 200 OK
Accept - Ranges: bytes
Cache - Control: private, no - cache, no - store, proxy - revalidate, no - transform
Connection: keep - alive
Content - Length: 277
Content - Type: text/html
Date: Sun, 16 Jun 2024 08:43:38 GMT
Etag: "575e1f71 - 115"
Last - Modified: Mon, 13 Jun 2016 02:50:25 GMT
Pragma: no - cache
Server: bfe/1.0.8.18
- DELETE方法(不常用)
- 用途:用于刪除文件,是PUT的相反方法。
- 示例:DELETE /example.html HTTP/1.1
- 特性:按請求URL刪除指定的資源。
- OPTIONS方法
- 用途:用于查詢針對請求URL指定的資源支持的方法。
- 示例:OPTIONS * HTTP/1.1
- 特性:返回允許的方法,如GET、POST等。
- C++示例(搭建nginx測試):
// 搭建一個nginx用來測試
// sudo apt install nginx
// sudo nginx -- 開啟
// ps ajx | grep nginx -- 查看
// sudo nginx -s stop -- 停止服務$ ps ajx | grep nginx
$ sudo nginx -s stop
$ ps ajx | grep nginx// 指明方法
$ curl -X OPTIONS -i http://127.0.0.1/
HTTP/1.1 405 Not Allowed
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 16 Jun 2024 08:48:22 GMT
Content - Type: text/html
Content - Length: 165
Connection: keep - alive
Connection: keep - alive<!DOCTYPE html>
<head><title>405 Not Allowed</title></head>
<body>
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx/1.18.0 (Ubuntu)</center>
</body>
// 支持的效果
$ curl -X OPTIONS -i http://127.0.0.1/
HTTP/1.1 200 OK
Allow: GET, HEAD, POST, OPTIONS
Content - Type: text/plain
Server: nginx/1.18.0 (Ubuntu)
Date: Sun, 16 Jun 2024 09:04:44 GMT
Access - Control - Allow - Origin: *
Access - Control - Allow - Headers: Content - Type, Authorization
// 注意:這里沒有響應體,因為Content - Length為0
HTTP的狀態碼
狀態碼類別 | 類別描述 | 原因短語 |
---|---|---|
1XX | Informational(信息性狀態碼) | 接收的請求正在處理 |
2XX | Success(成功狀態碼) | 請求正常處理完畢 |
3XX | Redirection(重定向狀態碼) | 需要進行附加操作以完成請求 |
4XX | Client Error(客戶端錯誤狀態碼) | 服務器無法處理請求 |
5XX | Server Error(服務器錯誤狀態碼) | 服務器處理請求出錯 |
最常見的狀態碼如200(OK)、404(Not Found)、403(Forbidden)、302(Redirect, 重定向) 。
狀態碼 | 含義 | 應用樣例 |
---|---|---|
100 | Continue | 上傳大文件時,服務器告訴客戶端可以繼續上傳 |
200 | OK | 訪問網站首頁,服務器返回網頁內容 |
201 | Created | 發布新文章,服務器返回文章創建成功的信息 |
204 | No Content | 刪除文章后,服務器返回“無內容”表示操作成功 |
301 | Permanently Moved | 網站換域名后,搜索引擎更新網站,自動跳轉到新域名 |
302 | Found 或 See Other | 用戶登錄成功后,重定向到用戶首頁 |
304 | Not Modified | 瀏覽器緩存機制,對未修改的資源返回304狀態碼 |
400 | Bad Request | 填寫表單時,格式不正確導致提交失敗 |
401 | Unauthorized | 訪問需要登錄的頁面時,未登錄或認證失敗 |
403 | Forbidden | 嘗試訪問沒有權限查看的頁面 |
404 | Not Found | 訪問不存在的網頁鏈接 |
500 | Internal Server Error | 服務器崩潰或數據庫錯誤導致頁面無法加載 |
502 | Bad Gateway | 使用代理服務器時,代理服務器無法從上游服務器獲取有效響應 |
503 | Service Unavailable | 服務器維護或過載,暫時無法處理請求 |
關于重定向的驗證
301代表永久重定向,302代表臨時重定向,都依賴Location
選項。
- HTTP狀態碼301(永久重定向):表示請求的資源已經被永久移動到新的位置。在這種情況下,服務器會在響應中添加一個Location頭部,用于指定資源的新位置。例如,在HTTP響應中,可能會看到類似于以下的頭部信息:
HTTP/1.1 301 Moved Permanently
Location: //www.new-url.com
- HTTP狀態碼302(臨時重定向):當服務器返回HTTP 302狀態碼時,表示請求的資源臨時被移動到新位置。同樣地,服務器也會在響應中添加一個Location頭部來指定資源的新位置。瀏覽器會使用新的URL進行后續請求,但不會緩存這個重定向。例如,在HTTP響應中,可能會看到類似于以下的頭部信息:
HTTP/1.1 302 Found
Location: //www.new-url.com
總結:無論是HTTP 301還是HTTP 302重定向,都需要依賴Location選項來指定資源的新位置。在這兩個狀態碼的HTTP響應頭部,用于告訴瀏覽器應該將請求重定向到哪個新的URL地址。
HTTP常見Header
- Content-Type:數據類型(text/html等 )
- Content-Length:Body的長度
- Host:客戶端告知服務器,所請求的資源是在哪個主機的哪個端口上;
- User-Agent:聲明用戶的操作系統和瀏覽器版本信息;
- referer:當前頁面是從哪個頁面跳轉過來的;
- Location:搭配3xx狀態碼使用,告訴客戶端接下來要去哪里訪問;
- Cookie:用于在客戶端存儲少量信息,通常用于實現會話(session)的功能;
關于connection報頭
HTTP中的Connection字段是HTTP報文頭的一部分,它主要用于控制和管理客戶端與服務器之間的連接狀態。
核心作用
- 管理持久連接:Connection字段還用于管理持久連接(也稱為長連接)。持久連接允許客戶端和服務器在請求/響應完成后不立即關閉TCP連接,以便在同一個連接上發送多個請求和接收多個響應。
持久連接(長連接)
- HTTP/1.1:在HTTP/1.1協議中,默認使用持久連接。當客戶端和服務器都不明確指定關閉連接時,連接將保持打開狀態,以便后續的請求和響應可以復用同一個連接。
- HTTP/1.0:在HTTP/1.0協議中,默認連接是非持久的。如果希望在HTTP/1.0上實現持久連接,需要在請求頭中顯式設置Connection: keep-alive。
語法格式
- Connection: keep-alive:表示希望保持連接以復用TCP連接。
- Connection: close:表示請求/響應完成后,應該關閉TCP連接。
下面附上一張關于HTTP常見header的表格
字段名 | 含義 | 樣例 |
---|---|---|
Accept | 客戶端可接受的響應內容類型 | Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,/;q=0.8 |
Accept-Encoding | 客戶端支持的數據壓縮格式 | Accept-Encoding: gzip, deflate, br |
Accept-Language | 客戶端可接受的語言類型 | Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 |
Host | 請求的主機名和端口號 | Host: www.example.com:8080 |
User-Agent | 客戶端的軟件環境信息 | User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36 |
Cookie | 客戶端發送給服務器的HTTP cookie信息 | Cookie: session_id=abcdefg12345; user_id=123 |
Referer | 請求的來源URL | Referer: http://www.example.com/previous_page.html |
Content-Type | 實體主體的媒體類型 | Content-Type: application/x-www-form-urlencoded (對于表單提交) 或 Content-Type: application/json (對于JSON數據) |
Content-Length | 實體主體的字節大小 | Content-Length: 150 |
Authorization | 認證信息,如用戶名和密碼 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== (Base64編碼后的用戶名:密碼) |
Cache-Control | 緩存控制指令 | 請求時: Cache-Control: no-cache 或 Cache-Control: max-age=3600; 響應時: Cache-Control: public, max-age=3600 |
Connection | 請求完后是關閉還是保持連接 | Connection: keep-alive 或 Connection: close |
Date | 請求或響應的日期和時間 | Date: Wed, 21 Oct 2023 07:28:00 GMT |
Location | 重定向的目標URL(與3xx狀態碼配合使用) | Location: http://www.example.com/new_location.html (與302狀態碼配合使用) |
Server | 服務器類型 | Server: Apache/2.4.41 (Unix) |
Last-Modified | 資源的最后修改時間 | Last-Modified: Wed, 21 Oct 2023 07:20:00 GMT |
ETag | 資源的唯一標識符,用于緩存 | ETag: “3f80f-1b6-5f4e2512a4100” |
Expires | 響應過期的日期和時間 | Expires: Wed, 21 Oct 2023 08:28:00 GMT |