HTTP協(xié)議
Web瀏覽器和Web服務(wù)器程序進(jìn)行數(shù)據(jù)交換,發(fā)送請(qǐng)求和應(yīng)答時(shí),要遵循一定的協(xié)議(不然也無(wú)法解析數(shù)據(jù))煎谍,這個(gè)協(xié)議就是超文本傳輸協(xié)議(Hyper Text Transfer Protocol, HTTP).
HTTP協(xié)議使用TCP協(xié)議作為支持坊萝,為其提供可靠的數(shù)據(jù)傳輸服務(wù)。
-
Web瀏覽器和Web服務(wù)器
Paste_Image.png
HTTP1.1特性
- 應(yīng)用層協(xié)議: HTTP工作在應(yīng)用層句狼, 運(yùn)輸層使用TCP協(xié)議笋熬, 默認(rèn)端口為80
- 基于C/S模式: 客戶端通過(guò)瀏覽器(并非一定是瀏覽器)向服務(wù)器發(fā)出請(qǐng)求, 服務(wù)器向客戶端返回對(duì)請(qǐng)求的應(yīng)答腻菇。
- 雙向傳輸: 客戶端向服務(wù)器發(fā)送請(qǐng)求胳螟, 服務(wù)器向客戶端回應(yīng)信息昔馋, 客戶端負(fù)責(zé)將回應(yīng)信息解析呈現(xiàn)給用戶√撬剩客戶端也可以將諸如表單一類的信息發(fā)送給服務(wù)器秘遏。
- 支持多個(gè)主機(jī)名: HTTP1.1版本允許一個(gè)Web服務(wù)器處理幾十個(gè)甚至幾百個(gè)虛擬機(jī)的請(qǐng)求。
- 持久連接:允許客戶機(jī)在一個(gè)TCP連接中發(fā)送多個(gè)相關(guān)文檔的請(qǐng)求嘉竟。 HTTP1.0以前的版本一個(gè)請(qǐng)求需要一個(gè)新的TCP連接邦危。
- 部分資源選擇: 允許客戶機(jī)只要求文檔的部分資源的請(qǐng)求, 這樣可以減少服務(wù)器的負(fù)載舍扰, 節(jié)省了資源倦蚪。
- 支持高速緩存的代理: Web瀏覽器將用戶瀏覽過(guò)的網(wǎng)頁(yè)內(nèi)容緩存在本機(jī)高速緩存中; 亦可在客戶機(jī)和服務(wù)器之間建立代理服務(wù)器边苹, 將本網(wǎng)絡(luò)中曾經(jīng)訪問(wèn)過(guò)的網(wǎng)頁(yè)緩存在本地代理服務(wù)器中陵且,客戶端優(yōu)先從代理服務(wù)器中讀取信息, 減少不必要的Internet訪問(wèn)流量个束。
- 內(nèi)容協(xié)商: 通過(guò)內(nèi)容協(xié)商特性完成客戶機(jī)和服務(wù)器的信息交換滩报, 確定傳輸?shù)募?xì)節(jié)。
- 安全性好:使用鑒別方法提高安全性能播急。
HTTP的工作過(guò)程
- 客戶機(jī)與服務(wù)器交互過(guò)程
- Web服務(wù)器監(jiān)聽本地80端口脓钾。等待請(qǐng)求。
- 建立連接桩警。由TCP協(xié)議建立連接可训, 開啟一條傳輸通道, 提供數(shù)據(jù)傳輸?shù)谋U稀?/li>
- 客戶端發(fā)出請(qǐng)求捶枢。連接建立后握截, 即可向服務(wù)器發(fā)出請(qǐng)求, 獲取數(shù)據(jù)烂叔。請(qǐng)求封裝在HTTP請(qǐng)求報(bào)文中谨胞。
- Web服務(wù)器應(yīng)答請(qǐng)求。 收到請(qǐng)求后蒜鸡, Web服務(wù)器將應(yīng)答和對(duì)應(yīng)文件放入HTTP應(yīng)答報(bào)文中胯努, 發(fā)送給客戶端。
- 重復(fù)3逢防, 4
- 通信結(jié)束叶沛, 關(guān)閉連接。
HTTP無(wú)狀態(tài)特性
服務(wù)器不去記錄訪問(wèn)的客戶端忘朝。
持久連接和非持久連接
HTTP1.1默認(rèn)使用持久連接灰署。
- 持久連接
可一次連接請(qǐng)求多個(gè)文件
- 非持久連接
每次連接只能請(qǐng)求一個(gè)文件
HTTP報(bào)文
報(bào)文有請(qǐng)求和應(yīng)答兩種。一般以文本形式發(fā)送。
請(qǐng)求報(bào)文
客戶端使用溉箕,指明所需文檔的名字和位置晦墙。
-
報(bào)文結(jié)構(gòu)
GET報(bào)文
最常用的的報(bào)文,請(qǐng)求參數(shù)以?para=val¶2=val2的形式加在URL后面肴茄。實(shí)體是空的晌畅,GET方式一般用來(lái)請(qǐng)求數(shù)據(jù)。當(dāng)然要用來(lái)提交數(shù)據(jù)也沒有人可以阻止你就是了独郎。踩麦。。
- Host: 表示所要訪問(wèn)的主機(jī)氓癌。Host字段與方法字段結(jié)合谓谦,可以明確要訪問(wèn)的資源。如上圖中一個(gè)完整的URL應(yīng)當(dāng)是:http://i0.wp.com/ooly.club/pzyyll/wp-content/uploads/2016/04/cropped-b_authentique1.jpg?resize-825%2c510
- Connection: 告訴服務(wù)器對(duì)客戶端做出應(yīng)答后贪婉,是否保持連接反粥,上圖中的Keep-Alive,表示保持連接疲迂。例如一個(gè)網(wǎng)頁(yè)文件中可能有多個(gè)圖片連接才顿,保持連接可以不斷開連接而繼續(xù)下載圖片文件,提高效率和響應(yīng)速度尤蒿。
- Accept: 表示客戶端所接受的文檔類型郑气。常見的還有 image/gif, image/jpeg, application/vnd.ms-word等等腰池。
- User-Agent: 表示客戶端類型尾组。可以用于讓服務(wù)器根據(jù)客戶端類型返回應(yīng)答內(nèi)容示弓,防止出現(xiàn)客戶端無(wú)法理解應(yīng)答的現(xiàn)象讳侨。
- Referer: HTTP參照位址(referer,或HTTP referer)奏属,是HTTP表頭的一個(gè)欄位跨跨,用來(lái)表示從哪兒連結(jié)到目前的網(wǎng)頁(yè),採(cǎi)用的格式是URL囱皿。換句話說(shuō)勇婴,藉著HTTP參照位址,目前的網(wǎng)頁(yè)可以檢查訪客從哪裡而來(lái)铆帽,這也常被用來(lái)對(duì)付偽造的跨網(wǎng)站請(qǐng)求咆耿。
- Accept-Encoding: 表示客戶端能夠理解的編碼方式。
- Accept-Language: 表示客戶端優(yōu)先接受的語(yǔ)言類型爹橱, 服務(wù)器可以根據(jù)語(yǔ)言的不同返回不同版本的主頁(yè)。
POST報(bào)文
另一個(gè)最常用的請(qǐng)求報(bào)文,一般用于提交數(shù)據(jù)愧驱,或請(qǐng)求參數(shù)比較敏感的慰技,例如密碼信息等。因?yàn)橛肞OST方式提交的數(shù)據(jù)都會(huì)放在請(qǐng)求報(bào)文的實(shí)體中组砚。
POST報(bào)文的首部行還常常會(huì)用到下面這個(gè):
- Content-type: (實(shí)體解析類型)
詳細(xì)表單內(nèi)容類型
較為常用的就是以下兩種:- application/x-www-form-urlencoded
- multipart/form-data
- 另外還有
- application/json
- text/xml
- 等等
用一個(gè)例子作為說(shuō)明吻商,比如我要傳遞一個(gè)下面的表單信息:
Name:Zhili Cai
Pwd:1234567
Email: pzyyll@gmail.com
1.application/x-www-form-urlencoded: 用這種方式的實(shí)體內(nèi)容的鍵值對(duì)用“KEY=VAL&KEY2=VAL2&..."的方法表示。并且會(huì)對(duì)KEY和VAL中的某些字符進(jìn)行URI Encoding轉(zhuǎn)義糟红,具體有哪些可以參照這個(gè)艾帐,對(duì)于空格的處理是轉(zhuǎn)換為‘+’.
POST /post.php HTTP/1.1/r/n
...
Content_type: charset=utf-8; application/x-www-form-urlencoded/r/n
/r/n //記得首部行與實(shí)體之間空一行
Name=Zhili+Cai&Pwd=1234567&Email=+pzyyll%40gmail.com
2.multipart/form-data:這種方式的實(shí)體就稍微有點(diǎn)復(fù)雜了,除了要指明content_type外盆偿,還要設(shè)置一個(gè)分隔字符串boundary柒爸,詳細(xì)見下面:
POST /post.php HTTP/1.1
...
Content_type: multipart/form-data; boundary=abcdefghijklmn
//實(shí)體與首部行之間空一行
--abcdefghijklmn //分割符前還要再加--
Content-Disposition: form-data; name="Name"
//內(nèi)容與首部行之間空一行
Zhili Cai
--abcdefghijklmn
Content-Disposition:form-data; name="Pwd"
1234567
--abcdefghijklmn
Content-Disposition:form-data; name="Email"
pzyyll@gmail.com
--abcdefghijklmn-- //結(jié)束--boundary--
另外boundary還可以嵌套,以下是摘自官方文檔的
Content-Type: multipart/form-data; boundary=AaB03x
--AaB03x
Content-Disposition: form-data; name="submit-name"
Larry
--AaB03x
Content-Disposition: form-data; name="files"
Content-Type: multipart/mixed; boundary=BbC04y
--BbC04y
Content-Disposition: file; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--BbC04y
Content-Disposition: file; filename="file2.gif"
Content-Type: image/gif
Content-Transfer-Encoding: binary
...contents of file2.gif...
--BbC04y--
--AaB03x--
Content-Disposition 用來(lái)指示出內(nèi)容的類型事扭,例如還有attachment捎稚,表示附件。具體可以查看文檔
3.application/json: 需要瀏覽器和服務(wù)器支持
POST /post.php HTTP/1.1
...
Content_type: charset=utf-8; application/json
//記得首部行與實(shí)體之間空一行
{"Name":"Zhili Cai", "Pwd":"1234567", "Email":" pzyyll@gmail.com"}
其它的請(qǐng)求方法還有HEAD, PUT, DELETE等
- HEAD:與GET類似求橄,但是應(yīng)答報(bào)文無(wú)實(shí)體內(nèi)容今野,一般用于檢測(cè)URI是否有效,能否被訪問(wèn)罐农。
- PUT:用于將一個(gè)文檔上傳到服務(wù)器上条霜,文檔內(nèi)容存儲(chǔ)在實(shí)體中, 服務(wù)器根據(jù)URI創(chuàng)建一個(gè)新文檔涵亏,并將實(shí)體內(nèi)容存入新文檔中宰睡,如果文檔在服務(wù)器上已經(jīng)存在,則會(huì)覆蓋舊文檔溯乒。執(zhí)行成功返回對(duì)應(yīng)的應(yīng)答報(bào)文夹厌,失敗則報(bào)錯(cuò)。
- DELETE:用來(lái)刪除服務(wù)器上的文檔裆悄。
各種方式可以查看RFC2616的第9章
應(yīng)答報(bào)文
結(jié)構(gòu)與請(qǐng)求報(bào)文類似矛纹,但是第一行是狀態(tài)行,不是請(qǐng)求行了光稼。
一個(gè)實(shí)例:
--> HTTP/1.1 302 Found
Server: nginx
Date: Wed, 04 May 2016 06:06:52 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/5.4.41
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Cache-Control: no-cache, must-revalidate, max-age=0
Pragma: no-cache
Set-Cookie: [52 bytes were stripped]
X-Frame-Options: SAMEORIGIN
Set-Cookie: [257 bytes were stripped]
Set-Cookie: [247 bytes were stripped]
Set-Cookie: [249 bytes were stripped]
Location: http://ooly.club/pzyyll/wp-admin/
另外再補(bǔ)充下或南,現(xiàn)在的HTTP協(xié)議已經(jīng)到版本2了,請(qǐng)求行和狀態(tài)行,首部行和現(xiàn)在的不太一樣
感興趣的可以查看文檔RFC7540
GET /resource HTTP/1.1 HEADERS
Host: example.org ==> + END_STREAM
Accept: image/jpeg + END_HEADERS
:method = GET
:scheme = https
:path = /resource
host = example.org
accept = image/jpeg
/******************************************************/
POST /resource HTTP/1.1 HEADERS
Host: example.org ==> - END_STREAM
Content-Type: image/jpeg - END_HEADERS
Content-Length: 123 :method = POST
:path = /resource
{binary data} :scheme = https
CONTINUATION
+ END_HEADERS
content-type = image/jpeg
host = example.org
content-length = 123
DATA
+ END_STREAM
{binary data}
/******************************************************/
HTTP/1.1 100 Continue HEADERS
Extension-Field: bar ==> - END_STREAM
+ END_HEADERS
:status = 100
extension-field = bar
HTTP/1.1 200 OK HEADERS
Content-Type: image/jpeg ==> - END_STREAM
Transfer-Encoding: chunked + END_HEADERS
Trailer: Foo :status = 200
content-length = 123
123 content-type = image/jpeg
{binary data} trailer = Foo
0
Foo: bar DATA
- END_STREAM
{binary data}
HEADERS
+ END_STREAM
+ END_HEADERS
foo = bar
首部行中還有一個(gè)Cookie來(lái)記錄用戶行為艾君,現(xiàn)在也用的比較廣采够。