一、應(yīng)用層協(xié)議
我們已經(jīng)學(xué)過(guò) TCP/IP
, 已然知道數(shù)據(jù)能從客戶(hù)端進(jìn)程經(jīng)過(guò)路徑選擇跨網(wǎng)絡(luò)傳送到服務(wù)器端進(jìn)程。
我們還需要知道的是,我們把數(shù)據(jù)從 A
端傳送到 B
端, TCP/IP 解決的是順豐的功能,而兩端還要對(duì)數(shù)據(jù)進(jìn)行加工處理或者使用,所以我們還需要一層協(xié)議,不關(guān)心通信細(xì)節(jié),關(guān)心應(yīng)用細(xì)節(jié)!這層協(xié)議叫做應(yīng)用層協(xié)議。而應(yīng)用是有不同的場(chǎng)景的,因此應(yīng)用層協(xié)議經(jīng)常是需要“自定義協(xié)議”的,通常情況下可以基于一些設(shè)計(jì)好的協(xié)議進(jìn)行定制,HTTP
之所以應(yīng)用特別廣,主要原因就是可定制性特別強(qiáng)。
二、HTTP 報(bào)文格式
學(xué)習(xí) HTTP 協(xié)議最主要的就是認(rèn)識(shí)它的報(bào)文格式。我們可以通過(guò)抓包來(lái)獲取到 HTTP 的報(bào)文格式,下面以瀏覽器訪問(wèn)百度時(shí)的請(qǐng)求響應(yīng)為例進(jìn)行抓包:
抓包原理:
抓包工具 相當(dāng)于一個(gè) “代理”。瀏覽器訪問(wèn) www.baidu.com 時(shí), 就會(huì)把 HTTP 請(qǐng)求先發(fā)給 抓包工具,抓包工具 再把請(qǐng)求轉(zhuǎn)發(fā)給 百度 的服務(wù)器。當(dāng) 百度 服務(wù)器返回?cái)?shù)據(jù)時(shí),抓包工具 拿到返回?cái)?shù)據(jù),再把數(shù)據(jù)交給瀏覽器。因此 抓包工具 對(duì)于瀏覽器和 百度 服務(wù)器之間交互的數(shù)據(jù)細(xì)節(jié),都是非常清楚的。
HTTP 請(qǐng)求 抓包結(jié)果:
注解:
首行
: [方法] + [url] + [版本]Header
: 請(qǐng)求的屬性, 冒號(hào)分割的鍵值對(duì);每組屬性之間使用\n分隔空行
: 遇到空行表示Header部分結(jié)束Body
: 空行后面的內(nèi)容都是Body。Body允許為空字符串,如果Body存在,則在Header中會(huì)有一個(gè)Content-Length屬性來(lái)標(biāo)識(shí)Body的長(zhǎng)度
HTTP 響應(yīng) 抓包結(jié)果:
注解:
首行
: [版本號(hào)] + [狀態(tài)碼] + [狀態(tài)碼解釋]Header
: 請(qǐng)求的屬性, 冒號(hào)分割的鍵值對(duì);每組屬性之間使用\n分隔空行
: 遇到空行表示Header部分結(jié)束Body
: 空行后面的內(nèi)容都是Body。Body允許為空字符串,如果Body存在, 則在Header中會(huì)有一個(gè)Content-Length屬性來(lái)標(biāo)識(shí)Body的長(zhǎng)度
HTTP 協(xié)議格式總結(jié):
空行的作用:
HTTP 協(xié)議并沒(méi)有規(guī)定報(bào)頭部分的鍵值對(duì)有多少個(gè),空行就相當(dāng)于是 “報(bào)頭的結(jié)束標(biāo)記”,或者是 “報(bào)頭和正文之間的分隔符”。
三、HTTP 請(qǐng)求詳解
1、首行
(1)請(qǐng)求方法:
請(qǐng)求方法 | 描述 |
---|---|
GET | 從服務(wù)器獲取資源 |
POST | 向指定服務(wù)器資源提交數(shù)據(jù)進(jìn)行處理請(qǐng)求(例如提交表單或上傳文件)。數(shù)據(jù)被包含在請(qǐng)求體中。POST 請(qǐng)求可能會(huì)導(dǎo)致新的資源的建立和/或已有資源的修改。 |
HEAD | 類(lèi)似于 GET 請(qǐng)求,只不過(guò)返回的響應(yīng)中沒(méi)有具體的內(nèi)容,用于獲取報(bào)頭。 |
PUT | 從客戶(hù)端向服務(wù)器傳送的數(shù)據(jù)取代指定的文檔的內(nèi)容。 |
DELETE | 請(qǐng)求服務(wù)器刪除指定的頁(yè)面。 |
CONNECT | HTTP/1.1 協(xié)議中預(yù)留給能夠?qū)⑦B接改為管道方式的代理服務(wù)器。 |
OPTIONS | 允許客戶(hù)端查看服務(wù)器的性能。 |
TRACE | 回顯服務(wù)器收到的請(qǐng)求,主要用于測(cè)試或診斷。 |
PATCH | 是對(duì) PUT 方法的補(bǔ)充,用來(lái)對(duì)已知資源進(jìn)行局部更新。 |
HTTP的請(qǐng)求方法,描述了這個(gè)HTTP請(qǐng)求想干什么。HTTP協(xié)議有很多的請(qǐng)求方法,不同的方法表示不同的語(yǔ)義。其中 GET
方法(表示從服務(wù)器獲取資源)和 POST
方法(表示向服務(wù)器提交數(shù)據(jù)資源,登錄、上傳文件等場(chǎng)景下)是常用到的方法,而 GET 又是最常用的方法,至于其他方法我們很少會(huì)用得上。
因此有這樣一句話:天下HTTP請(qǐng)求分十斗,GET請(qǐng)求獨(dú)占八斗,POST請(qǐng)求占一斗,其他方法請(qǐng)求共占一斗。
GET 和 POST 的區(qū)別
雖然 GET
和 POST
表示不同語(yǔ)義,但實(shí)際上 HTTP 的語(yǔ)義只是一種建議,在實(shí)際使用的時(shí)候不一定非要遵守。因此 GET 和 POST 沒(méi)有本質(zhì)上的區(qū)別,使用GET的場(chǎng)景,替換換成POST也沒(méi)有問(wèn)題,使用POST的場(chǎng)景替換成GET也可以。但是二者在使用習(xí)慣上存在區(qū)別:
- 使用 GET 請(qǐng)求傳參到后臺(tái)時(shí),傳遞的參數(shù)則顯示在地址欄,安全性低,且參數(shù)的長(zhǎng)度也有限制(2048字符);POST 請(qǐng)求則是將傳遞的參數(shù)放在 request body 中,不會(huì)在地址欄顯示,安全性比 GET 請(qǐng)求高,且參數(shù)沒(méi)有長(zhǎng)度限制。(重要區(qū)別)
- GET習(xí)慣上用來(lái)表示 獲取數(shù)據(jù),POST 用來(lái)表示提交數(shù)據(jù)。
- GET一般沒(méi)有 body,需要攜帶的數(shù)據(jù)通常放到URL中,POST一般有 body,將需要攜帶的數(shù)據(jù)放到 body 中。
- GET請(qǐng)求可以被瀏覽器收藏,POST請(qǐng)求不可以。(當(dāng)我們收藏一個(gè)鏈接時(shí),瀏覽器會(huì)記錄該鏈接的 URL,GET 請(qǐng)求可以被瀏覽器收藏,因?yàn)檎?qǐng)求參數(shù)包含在 URL 中,而 POST 請(qǐng)求不能被瀏覽器直接收藏,因?yàn)檎?qǐng)求數(shù)據(jù)位于請(qǐng)求體中,無(wú)法完整保存在收藏夾中)
- GET請(qǐng)求通常設(shè)計(jì)出冪等的,POST 請(qǐng)求一般是不冪等的。(如果多次請(qǐng)求得到的結(jié)果一樣, 就視為請(qǐng) 求是冪等的)
- 承接上述冪等性的前提下,GET 可以被緩存,POST 不能被緩存。
(2)URL
URL(Uniform Resource Locator)是統(tǒng)一資源定位符的縮寫(xiě)。它是用于標(biāo)識(shí)和定位互聯(lián)網(wǎng)上的資源(如網(wǎng)頁(yè)、圖像、視頻等)的字符串格式。
例如:
https://cn.bing.com/videos/search?q=abcde&form=Z9LH1
- 協(xié)議:常見(jiàn)的有 http 和 https,也有其他的類(lèi)型。(例如訪問(wèn) mysql 時(shí)用的jdbc:mysql )
- 登陸信息(認(rèn)證):現(xiàn)在的網(wǎng)站進(jìn)行身份認(rèn)證一般不再通過(guò) URL 進(jìn)行了,一般都會(huì)省略
- 服務(wù)器地址:此處是一個(gè) “域名”,域名會(huì)通過(guò) DNS 系統(tǒng)解析成一個(gè)具體的 IP 地址(通過(guò) ping 命令可以看到域名真實(shí) IP 地址 )
- 端口號(hào)(可選):指定了與服務(wù)器建立連接時(shí)要使用的端口。當(dāng)端口號(hào)省略的時(shí)候,瀏覽器會(huì)根據(jù)協(xié)議類(lèi)型自動(dòng)決定使用哪個(gè)端口。例如 http 協(xié)議默認(rèn)使用 80 端口,https 協(xié)議默認(rèn)使用 443 端口
- 帶層次的文件路徑:表示要訪問(wèn)的資源在服務(wù)器上的路徑或文件信息
- 查詢(xún)字符串(query string)(可選):對(duì)請(qǐng)求資源進(jìn)行細(xì)節(jié)上的補(bǔ)充。本質(zhì)是一個(gè)鍵值對(duì)結(jié)構(gòu),鍵值對(duì)之間使用& 分隔,鍵和值之間使用 = 分隔
- 片段標(biāo)識(shí)(可選):片段標(biāo)識(shí)主要用于頁(yè)面內(nèi)跳轉(zhuǎn)
(3) 版本號(hào)
在HTTP協(xié)議的首行中還包含另一個(gè)字段,叫做“版本號(hào)”。
版本號(hào)是指明正在使用的HTTP協(xié)議版本的一部分。常見(jiàn)的HTTP協(xié)議版本包括
HTTP/1.0
、HTTP/1.1
、HTTP/2
、HTTP/3
等。它用于指示客戶(hù)端和服務(wù)器之間所使用的協(xié)議版本,以確保雙方能夠正確解析和處理請(qǐng)求或響應(yīng)。當(dāng)前最主流的的版本是HTTP/1.1
,絕大部分互聯(lián)網(wǎng)上的網(wǎng)站用的都是 HTTP/1.1 版本。
2、請(qǐng)求報(bào)頭 Header
通過(guò)觀察上面的抓包情況,可以看到,請(qǐng)求頭是由鍵值對(duì)組成的。Header中的鍵值對(duì)大多都是HTTP協(xié)議規(guī)定的,當(dāng)然也可以添加自定義鍵值對(duì),這也是HTTP定制性強(qiáng)的體現(xiàn)。對(duì)于報(bào)頭中的每一個(gè)鍵值結(jié)構(gòu)都有自己的含義,下面介紹幾種比較常見(jiàn)的鍵值結(jié)構(gòu):
(1)Host:表示服務(wù)器主機(jī)的地址和端口。
大多數(shù)情況下,Host中的值和URL中的域名是一致的。那么為什么還要存在這樣一個(gè)鍵值結(jié)構(gòu)呢?這就要談到不一樣的情況了,當(dāng)我們?cè)L問(wèn)服務(wù)器不是直接訪問(wèn),而是通過(guò)代理訪問(wèn),此時(shí)的Host和URL中的域名就不一樣了。
(2)Content-Length:表示 body 中的數(shù)據(jù)長(zhǎng)度(字節(jié))。
Content-Length依賴(lài)于Body,如果一個(gè)請(qǐng)求沒(méi)有Body,Header中就沒(méi)有這個(gè)屬性。
(3)Content-Type:表示請(qǐng)求的 body 中的數(shù)據(jù)格式。
Content-Type
同樣依賴(lài)于 Body
,如果一個(gè)請(qǐng)求沒(méi)有Body,Header 中就沒(méi)有這個(gè)屬性。
作為請(qǐng)求,Content-Type 使用最多的是下面 兩種 格式:
1、
Content-Type: application/json;charset=UTF-8
這里表示數(shù)據(jù)是按照json格式組織的,并指定里數(shù)據(jù)的字符集為UTF-8
此時(shí)的body格式形如:
{"username":"xxxxx","password":"xxxxxxxx","uuid":"xxxxxxxxx","status":0}
2、
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
這里表示數(shù)據(jù)是按照表單提交的數(shù)據(jù)格式組織的,并指定里數(shù)據(jù)的字符集為UTF-8
此時(shí)的body格式和 query string
格式相同,形如:
username=tz&password=xxxxxxx&uuid=xxxxxxx&status=0
(4)User-Agent (簡(jiǎn)稱(chēng) UA):表示瀏覽器/操作系統(tǒng)的屬性
下面是我使用本機(jī)訪問(wèn)百度時(shí)的UA:
早期,由于同一時(shí)期的瀏覽器種類(lèi)繁多,功能參差不齊,UA可以在請(qǐng)求中告訴服務(wù)器,當(dāng)前的客戶(hù)端種類(lèi),服務(wù)器可以根據(jù)客戶(hù)端種類(lèi)推送不同的頁(yè)面。隨著時(shí)間的推移,瀏覽器之間的差異越來(lái)越小,UA存在的價(jià)值也就大打折扣了。雖然它還可以用來(lái)區(qū)分用戶(hù)使用的是手機(jī)、平板還是PC,但是“響應(yīng)式布局”相比之下是一種更好的方案。
(5)Referer:表示這個(gè)頁(yè)面是從哪個(gè)頁(yè)面跳轉(zhuǎn)過(guò)來(lái)的。
下面是我在百度主頁(yè)訪問(wèn)百度貼吧時(shí)的抓包情況:
注意: 如果直接在瀏覽器中輸入U(xiǎn)RL,或者直接通過(guò)收藏夾訪問(wèn)頁(yè)面時(shí)是沒(méi)有 Referer 的。(屬于直接訪問(wèn),沒(méi)有經(jīng)過(guò)跳轉(zhuǎn))
(6)Cookie 機(jī)制(重點(diǎn))
上面是一段 Cookie 信息,雖然看起來(lái)“有億點(diǎn)”扎眼,但也可以看的出 Cookie
也是由鍵值對(duì)組成,鍵和值之間使用=
分割,鍵值對(duì)之間使用;分割。至于這里的鍵值對(duì)都是程序眼自定義的數(shù)據(jù),不同的網(wǎng)站有不同的鍵值對(duì),也就有不同的含義和用途。
Cookie機(jī)制:是瀏覽器在本地存儲(chǔ)用戶(hù)自定義數(shù)據(jù)的一種關(guān)鍵機(jī)制。
瀏覽器自身也是要存儲(chǔ)一些數(shù)據(jù)的,比如最典型的就是用戶(hù)的身份信息。但是為了保證用戶(hù)的上網(wǎng)安全,瀏覽器會(huì)禁止網(wǎng)頁(yè)能夠直接訪問(wèn)硬盤(pán)。因此引出了Cookie機(jī)制,允許網(wǎng)頁(yè)通過(guò)瀏覽器提供的 API ,寫(xiě)入特定的文件中。
每個(gè)網(wǎng)站都存有自己的Cookie,Cookie是按照域名為維度進(jìn)行存儲(chǔ)的,通常同一個(gè)網(wǎng)站的主頁(yè)、結(jié)果頁(yè)、等子頁(yè)面共享同一份Cookie。不同的網(wǎng)站則是各自享有各自的Cookie。
Cookie從哪里來(lái)?
Cookie從服務(wù)器來(lái)。當(dāng)用戶(hù)首次訪問(wèn)一個(gè)網(wǎng)站時(shí),網(wǎng)站的服務(wù)器會(huì)在響應(yīng)中包含一個(gè)Set-Cookie頭部,該頭部包含了一條或多條Cookie信息。瀏覽器接收到這些Cookie信息后,會(huì)使用Cookie機(jī)制,將其保存在用戶(hù)的計(jì)算機(jī)或移動(dòng)設(shè)備上。
Cookie到哪里去?
Cookie在瀏覽器只是暫存,真正發(fā)揮作用得由服務(wù)器來(lái)使用。當(dāng)用戶(hù)在瀏覽器中發(fā)起新的請(qǐng)求訪問(wèn)同一網(wǎng)站時(shí),瀏覽器會(huì)自動(dòng)將該網(wǎng)站關(guān)聯(lián)的Cookie信息添加到請(qǐng)求的Cookie頭部中,并發(fā)送給服務(wù)器。這樣,服務(wù)器就能夠根據(jù)Cookie中的信息對(duì)用戶(hù)進(jìn)行個(gè)性化處理。
Cookie有什么用?
Cookie是本地瀏覽器存儲(chǔ)數(shù)據(jù)的機(jī)制。最典型的應(yīng)用就是存儲(chǔ)當(dāng)前用戶(hù)登錄的身份標(biāo)識(shí),也稱(chēng)為令牌(token)。當(dāng)然它存儲(chǔ)的也不一定是身份標(biāo)識(shí)信息,可以存儲(chǔ)任何字符串?dāng)?shù)據(jù)。(Cookie存儲(chǔ)空間有限,一般只有幾k,所以不會(huì)存儲(chǔ)較大的數(shù)據(jù))
3、正文Body
正文中的內(nèi)容格式和 header 中的 Content-Type 密切相關(guān),這里就不過(guò)多贅述了,大家可以多抓包熟悉一下。
三、HTTP響應(yīng)詳解
對(duì)于HTTP響應(yīng)來(lái)說(shuō),它的報(bào)文格式的絕大多數(shù)屬性都和HTTP請(qǐng)求相同,下面我就秉承著“求同存異”的原則向大家介紹:
1、狀態(tài)碼與狀態(tài)碼描述
狀態(tài)碼:表示訪問(wèn)一個(gè)頁(yè)面的結(jié)果。由三位數(shù)字組成,分為不同的類(lèi)別,每個(gè)類(lèi)別有特定的含義。
狀態(tài)碼描述:是對(duì)狀態(tài)碼的文字描述,用于更直觀地說(shuō)明該狀態(tài)碼所表示的含義。
但是對(duì)于HTTP提供的狀態(tài)碼種類(lèi)是非常繁多的,我們這里不可能一一介紹,下面是幾個(gè)常見(jiàn)的狀態(tài)碼及描述:
狀態(tài)碼 | 描述 | 含義 |
---|---|---|
200 | OK | 請(qǐng)求成功 |
404 | Not Found | 要訪問(wèn)的資源不存在 |
403 | Forbidden | 訪問(wèn)被拒絕(沒(méi)有權(quán)限) |
500 | Internal Server Error | 服務(wù)器內(nèi)部錯(cuò)誤 |
504 | Gateway Timeout | 服務(wù)器訪問(wèn)超時(shí)(服務(wù)器遲遲未響應(yīng)) |
301 | Moved Permanently | 臨時(shí)重定向 |
302 | Moved Temporarily (Found) | 永久重定向 |
關(guān)于重定向: 重定向就是訪問(wèn)舊的地址,被自動(dòng)引導(dǎo)到新的地址上。
雖然HTTP提供的狀態(tài)碼繁多,但我們可以根據(jù)狀態(tài)碼共性進(jìn)行劃分:
狀態(tài)碼 | 類(lèi)別 | 含義 |
---|---|---|
1XX | Informational | 接收的請(qǐng)求正在處理 |
2XX | Success | 請(qǐng)求正常處理完畢 |
3XX | Redirection | 需要進(jìn)行附加操作以完成請(qǐng)求 |
4XX | Client Error | 服務(wù)器無(wú)法處理請(qǐng)求 |
5XX | Server Error | 服務(wù)器處理請(qǐng)求出錯(cuò) |
2、怎樣構(gòu)造HTTP請(qǐng)求?
這里介紹 五種 常用的HTTP請(qǐng)求構(gòu)造方式:
(1)直接在瀏覽器地址欄輸入U(xiǎn)RL構(gòu)造出一個(gè)GET請(qǐng)求。
(2)HTML中的一些特殊標(biāo)簽也會(huì)觸發(fā)GET請(qǐng)求。例如link
、script
、img
、a
(3)使用 form表單 可以觸發(fā)GET和POST請(qǐng)求。
action:
構(gòu)造的 HTTP 請(qǐng)求的 URL 是什么.method:
構(gòu)造的 HTTP 請(qǐng)求的 方法 是 GET 還是 POST (form 只支持 GET 和 POST)
(4)使用AJAX可以構(gòu)造任意HTTP請(qǐng)求。
AJAX 全稱(chēng) Asynchronous JavaScript and XML 是一種用于在網(wǎng)頁(yè)上進(jìn)行異步數(shù)據(jù)交互的技術(shù),也是目前最主流的前后端交互方式。
關(guān)于同步和異步我們可以這樣理解:同步就是請(qǐng)求的發(fā)起者親自拿到請(qǐng)求的結(jié)果;異步就是請(qǐng)求的發(fā)起者并不關(guān)心結(jié)果,當(dāng)被請(qǐng)求的這一方計(jì)算出結(jié)果后,把結(jié)果推送給發(fā)起者。所以此時(shí)理解同步和異步,關(guān)鍵是看,結(jié)果是自己取還是別人送。
使用AJAX構(gòu)造HTTP請(qǐng)求:
由于 JS 提供的原生 AJAX API 很難用,這里我們使用 jQuery
中提供的 AJAX API 進(jìn)行操作:
$.ajax({
url:"https://www.baidu.com",// http請(qǐng)求中的url
type:"post",// 請(qǐng)求的方法,還可以是get、put、delete等
contentType:"text/plain",// body的數(shù)據(jù)類(lèi)型,可以是application/json等
// 這是一個(gè)處理響應(yīng)的回調(diào)函數(shù)
success: function(body) {
// 處理響應(yīng)的代碼
console.log(body);
}
});
上述過(guò)程中的回調(diào)函數(shù)會(huì)在服務(wù)器返回一個(gè)正確的響應(yīng)的時(shí)候自動(dòng)執(zhí)行,這個(gè)過(guò)程就是“異步”的。
具體來(lái)說(shuō),在頁(yè)面的JS中,把請(qǐng)求發(fā)送出去后就可以繼續(xù)執(zhí)行后續(xù)的代碼了,直到正確的響應(yīng)回來(lái)之后,瀏覽器會(huì)把這個(gè)響應(yīng)給success回調(diào)函數(shù),執(zhí)行并處理響應(yīng)的邏輯。
相比之下,ajax的功能更加豐富,但是也存在一個(gè)非常重要的問(wèn)題——跨域問(wèn)題
。
如果我們直接在本地執(zhí)行上述代碼,瀏覽器會(huì)報(bào)錯(cuò):
雖然報(bào)錯(cuò)了,但這并不是代碼的bug,而是瀏覽器引入的一種保護(hù)機(jī)制,為了防止a網(wǎng)站的頁(yè)面請(qǐng)求b網(wǎng)站的數(shù)據(jù)。
此時(shí)運(yùn)行的AJAX代碼運(yùn)行的頁(yè)面的域名是null(因?yàn)槭潜镜氐腍TML文件)請(qǐng)求的目標(biāo)域名是www.baidu.com,當(dāng)前二者域名不同,即使服務(wù)器返回響應(yīng),瀏覽器還是不能處理。
(5)使用現(xiàn)成工具構(gòu)造HTTP請(qǐng)求,如Postman。
這種現(xiàn)成的工具有很多,大家可以根據(jù)自己的口味,自行選擇,這里就不在過(guò)多介紹了。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-741511.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-741511.html
到了這里,關(guān)于應(yīng)用層協(xié)議 HTTP的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!