網(wǎng)絡(luò)協(xié)議
在互聯(lián)網(wǎng)通信基礎(chǔ)上,即信息能夠通過(guò)電纜,光纖球化,交換機(jī),路由器等硬件設(shè)備傳輸?shù)幕A(chǔ)上瓦糟,制定的通信雙方信息交互的格式筒愚,方式等
HTTP協(xié)議
目前絕大多數(shù)Web應(yīng)用都是使用HTTP協(xié)議進(jìn)行信息交互,包括每天訪問(wèn)的網(wǎng)站菩浙,手機(jī)上刷的APP等等
歷史起源
1960年美國(guó)人Ted Nelson構(gòu)思了一種通過(guò)計(jì)算機(jī)處理文本信息的方法巢掺,并稱之為超文本(hypertext),這成為了HTTP超文本傳輸協(xié)議標(biāo)準(zhǔn)架構(gòu)的發(fā)展根基
Ted Nelson組織協(xié)調(diào)萬(wàn)維網(wǎng)協(xié)會(huì)(World Wide Web Consortium)和互聯(lián)網(wǎng)工程工作小組(Internet Engineering Task Force )共同合作研究,最終發(fā)布了一系列的RFC劲蜻,HTTP協(xié)議是其中之一
注:網(wǎng)絡(luò)協(xié)議不是科學(xué)發(fā)現(xiàn)陆淀,只是人類(lèi)指定的標(biāo)準(zhǔn),任何人都可以指定協(xié)議先嬉,但前提是得有人遵守轧苫,很遺憾,我們錯(cuò)過(guò)了制定這些基礎(chǔ)標(biāo)準(zhǔn)的時(shí)間和機(jī)會(huì)
網(wǎng)絡(luò)層次
HTTP協(xié)議是應(yīng)用層協(xié)議疫蔓,這已經(jīng)是互聯(lián)網(wǎng)協(xié)議的最頂層了含懊,也就是直接與用戶交互的這一層了。在HTTP協(xié)議的下面一層衅胀,是TCP/IP協(xié)議岔乔。對(duì)于互聯(lián)網(wǎng)協(xié)議,會(huì)單獨(dú)寫(xiě)一篇文章來(lái)講
HTTP/0.9(已過(guò)時(shí))
最早版本滚躯,極為簡(jiǎn)單雏门,只有一個(gè)命令GET
請(qǐng)求:TCP 連接(connection)建立后嘿歌,客戶端向服務(wù)器請(qǐng)求(request)網(wǎng)頁(yè)index.html
注:關(guān)于TCP連接如何建立,會(huì)單獨(dú)在網(wǎng)絡(luò)協(xié)議的文章中講解
GET /index.html
返回:服務(wù)器只能回應(yīng)HTML格式的字符串茁影,不能回應(yīng)別的格式
<html>
<body>Hello World</body>
</html>
HTTP/1.0
第一宙帝,任何格式的內(nèi)容都可以發(fā)送,包括文字募闲,圖片步脓,視頻等二進(jìn)制
第二,3個(gè)命令:GET蝇更、POST、HEAD
第三呼盆,每次通信都必須包括頭信息(HTTP header)年扩,用來(lái)描述一些元數(shù)據(jù)
第四,新增狀態(tài)碼(status code)访圃、多字符集支持厨幻、多部分發(fā)送(multi-part type)、權(quán)限(authorization)腿时、緩存(cache)况脆、內(nèi)容編碼(content encoding)等
請(qǐng)求:第一行是請(qǐng)求命令,必須在尾部添加協(xié)議版本(HTTP/1.0)批糟。后面就是多行頭信息格了,描述客戶端的情況
GET /index.html HTTP/1.0
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
返回:頭信息 + 一個(gè)空行(\r\n)+ 數(shù)據(jù)。第一行是 協(xié)議版本 + 狀態(tài)碼(status code)+ 狀態(tài)描述
HTTP/1.0 200 OK
Content-Type: text/plain
Content-Length: 137582
Expires: Thu, 05 Dec 1997 16:00:00 GMT
Last-Modified: Wed, 5 August 1996 15:55:28 GMT
Server: Apache 0.84
<html>
<body>Hello World</body>
</html>
Content-Type
注:1.0版規(guī)定徽鼎,頭信息必須是 ASCII 碼盛末,后面的數(shù)據(jù)可以是任何格式。因此否淤,服務(wù)器回應(yīng)的時(shí)候悄但,必須告訴客戶端,數(shù)據(jù)是什么格式
text/plain
text/html
text/css
image/jpeg
audio/mp4
video/mp4
application/javascript
application/pdf
...
這些數(shù)據(jù)類(lèi)型總稱為MIME type石抡,每個(gè)值包括一級(jí)類(lèi)型和二級(jí)類(lèi)型檐嚣,之間用斜杠分隔
除了預(yù)定義的類(lèi)型,廠商也可以自定義類(lèi)型
application/vnd.debian.binary-package
注:上面的類(lèi)型表明啰扛,發(fā)送的是Debian系統(tǒng)的二進(jìn)制數(shù)據(jù)包
MIME type還可以在尾部使用分號(hào)嚎京,添加參數(shù)
Content-Type: text/html; charset=utf-8
注:上面的類(lèi)型表明,發(fā)送的是網(wǎng)頁(yè)隐解,而且編碼是UTF-8
MIME type不僅用在HTTP協(xié)議挖藏,還可以用在其他地方,比如HTML網(wǎng)頁(yè)
注:可能很多人寫(xiě)了很久的HTML頁(yè)面厢漩,都不知道m(xù)eta標(biāo)簽的細(xì)節(jié)和作用
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<!-- 等同于 -->
<meta charset="utf-8" />
使用帶有 http-equiv 屬性的 <meta> 標(biāo)簽時(shí)膜眠,服務(wù)器將把名稱/值對(duì)添加到發(fā)送給瀏覽器的內(nèi)容頭部,也就是HTTP協(xié)議的頭信息
content-type: text/html;charset:utf-8
Content-Encoding
由于發(fā)送的數(shù)據(jù)可以是任何格式,因此可以把數(shù)據(jù)壓縮后再發(fā)送宵膨。Content-Encoding字段說(shuō)明數(shù)據(jù)的壓縮方法
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
客戶端在請(qǐng)求時(shí)架谎,用Accept-Encoding字段說(shuō)明自己可以接受哪些壓縮方法
Accept-Encoding: gzip, deflate
缺點(diǎn)
HTTP/1.0 版的主要缺點(diǎn)是,每個(gè)TCP連接只能發(fā)送一個(gè)請(qǐng)求辟躏。發(fā)送數(shù)據(jù)完畢谷扣,連接就關(guān)閉,如果還要請(qǐng)求其他資源捎琐,就必須再新建一個(gè)連接
HTTP1.1
1997年1月会涎,HTTP/1.1 版本發(fā)布,只比 1.0 版本晚了半年瑞凑。一直用到了20年后的今天
持久連接
最大變化末秃,就是引入了持久連接(persistent connection),即TCP連接默認(rèn)不關(guān)閉籽御,可以被多個(gè)請(qǐng)求復(fù)用
客戶端和服務(wù)器發(fā)現(xiàn)對(duì)方一段時(shí)間沒(méi)有活動(dòng)练慕,就可以主動(dòng)關(guān)閉連接。不過(guò)技掏,規(guī)范的做法是铃将,客戶端在最后一個(gè)請(qǐng)求時(shí),發(fā)送Connection: close哑梳,明確要求服務(wù)器關(guān)閉TCP連接
Connection: close
目前劲阎,對(duì)于同一個(gè)域名,大多數(shù)瀏覽器允許同時(shí)建立6個(gè)持久連接
管道機(jī)制
引入了管道機(jī)制(pipelining)鸠真,即在同一個(gè)TCP連接里面哪工,客戶端可以同時(shí)發(fā)送多個(gè)請(qǐng)求。這樣就進(jìn)一步改進(jìn)了HTTP協(xié)議的效率
舉例來(lái)說(shuō)弧哎,客戶端需要請(qǐng)求兩個(gè)資源雁比。以前的做法是,在同一個(gè)TCP連接里面撤嫩,先發(fā)送A請(qǐng)求偎捎,然后等待服務(wù)器做出回應(yīng),收到后再發(fā)出B請(qǐng)求序攘。管道機(jī)制則是允許瀏覽器同時(shí)發(fā)出A請(qǐng)求和B請(qǐng)求茴她,但是服務(wù)器還是按照順序,先回應(yīng)A請(qǐng)求程奠,完成后再回應(yīng)B請(qǐng)求
返回:Content-Length 字段
一個(gè)TCP連接現(xiàn)在可以傳送多個(gè)回應(yīng)丈牢,Content-length字段的作用,聲明本次回應(yīng)的數(shù)據(jù)長(zhǎng)度
Content-Length: 3495
注:上面代碼告訴瀏覽器瞄沙,本次回應(yīng)的長(zhǎng)度是3495個(gè)字節(jié)己沛,后面的字節(jié)就屬于下一個(gè)回應(yīng)了
分塊傳輸編碼
使用Content-Length字段的前提條件是慌核,服務(wù)器發(fā)送回應(yīng)之前,必須知道回應(yīng)的數(shù)據(jù)長(zhǎng)度
對(duì)于一些很耗時(shí)的動(dòng)態(tài)操作來(lái)說(shuō)申尼,這意味著垮卓,服務(wù)器要等到所有操作完成,才能發(fā)送數(shù)據(jù)师幕,顯然這樣的效率不高
更好的處理方法是粟按,產(chǎn)生一塊數(shù)據(jù),就發(fā)送一塊霹粥,采用"流模式"(stream)取代"緩存模式"(buffer)
因此灭将,1.1版規(guī)定可以不使用Content-Length字段,而使用"分塊傳輸編碼"(chunked transfer encoding)后控。只要請(qǐng)求或回應(yīng)的頭信息有Transfer-Encoding字段庙曙,就表明回應(yīng)將由數(shù)量未定的數(shù)據(jù)塊組成
Transfer-Encoding: chunked
每個(gè)非空的數(shù)據(jù)塊之前,會(huì)有一個(gè)16進(jìn)制的數(shù)值忆蚀,表示這個(gè)塊的長(zhǎng)度矾利。最后是一個(gè)大小為0的塊姑裂,就表示本次回應(yīng)的數(shù)據(jù)發(fā)送完了
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked
25
This is the data in the first chunk
1C
and this is the second one
3
con
8
sequence
0
其他功能
新增了許多動(dòng)詞方法:PUT馋袜、PATCH、HEAD舶斧、 OPTIONS欣鳖、DELETE
另外,客戶端請(qǐng)求的頭信息新增了Host字段茴厉,用來(lái)指定服務(wù)器的域名
Host: www.example.com
有了Host字段泽台,就可以將請(qǐng)求發(fā)往同一臺(tái)服務(wù)器上的不同網(wǎng)站,為虛擬主機(jī)的興起打下了基礎(chǔ)
缺點(diǎn)
雖然1.1版允許復(fù)用TCP連接矾缓,但是同一個(gè)TCP連接里面怀酷,所有的數(shù)據(jù)通信是按次序進(jìn)行的。服務(wù)器只有處理完一個(gè)回應(yīng)嗜闻,才會(huì)進(jìn)行下一個(gè)回應(yīng)蜕依。要是前面的回應(yīng)特別慢,后面就會(huì)有許多請(qǐng)求排隊(duì)等著琉雳。這稱為"隊(duì)頭堵塞"(Head-of-line blocking)
為了避免這個(gè)問(wèn)題样眠,只有兩種方法:一是減少請(qǐng)求數(shù),二是同時(shí)多開(kāi)持久連接翠肘。這導(dǎo)致了很多的網(wǎng)頁(yè)優(yōu)化技巧檐束,比如合并腳本和樣式表、將圖片嵌入CSS代碼束倍、域名分片(domain sharding)等等被丧。如果HTTP協(xié)議設(shè)計(jì)得更好一些盟戏,這些額外的工作是可以避免的
注:這就是網(wǎng)頁(yè)優(yōu)化技巧使用的根本原因
HTTP/2
2015年,HTTP/2 發(fā)布晚碾,下一個(gè)新版本將直接是 HTTP/3
二進(jìn)制協(xié)議
HTTP/1.1 版的頭信息肯定是文本(ASCII編碼)抓半,數(shù)據(jù)體任意。HTTP/2 則是一個(gè)徹底的二進(jìn)制協(xié)議格嘁,頭信息和數(shù)據(jù)體都是二進(jìn)制笛求,并且統(tǒng)稱為"幀"(frame):頭信息幀和數(shù)據(jù)幀
二進(jìn)制協(xié)議的一個(gè)好處是,可以定義額外的幀糕簿。HTTP/2 定義了近十種幀探入,為將來(lái)的高級(jí)應(yīng)用打好了基礎(chǔ)。如果使用文本實(shí)現(xiàn)這種功能懂诗,解析數(shù)據(jù)將會(huì)變得非常麻煩蜂嗽,二進(jìn)制解析則方便得多
多工
HTTP/2 復(fù)用TCP連接,在一個(gè)連接里殃恒,客戶端和瀏覽器都可以同時(shí)發(fā)送多個(gè)請(qǐng)求或回應(yīng)植旧,而且不用按照順序一一對(duì)應(yīng),這樣就避免了"隊(duì)頭堵塞"
舉例來(lái)說(shuō)离唐,在一個(gè)TCP連接里面病附,服務(wù)器同時(shí)收到了A請(qǐng)求和B請(qǐng)求,于是先回應(yīng)A請(qǐng)求亥鬓,結(jié)果發(fā)現(xiàn)處理過(guò)程非常耗時(shí)完沪,于是就發(fā)送A請(qǐng)求已經(jīng)處理好的部分, 接著回應(yīng)B請(qǐng)求嵌戈,完成后覆积,再發(fā)送A請(qǐng)求剩下的部分
注:這樣雙向的、實(shí)時(shí)的通信熟呛,就叫做多工(Multiplexing)
數(shù)據(jù)流
因?yàn)?HTTP/2 的數(shù)據(jù)包是不按順序發(fā)送的宽档,同一個(gè)連接里面連續(xù)的數(shù)據(jù)包,可能屬于不同的回應(yīng)庵朝。因此吗冤,必須要對(duì)數(shù)據(jù)包做標(biāo)記,指出它屬于哪個(gè)回應(yīng)偿短。
HTTP/2 將每個(gè)請(qǐng)求或回應(yīng)的所有數(shù)據(jù)包欣孤,稱為一個(gè)數(shù)據(jù)流(stream)。每個(gè)數(shù)據(jù)流都有一個(gè)獨(dú)一無(wú)二的編號(hào)昔逗。數(shù)據(jù)包發(fā)送的時(shí)候降传,都必須標(biāo)記數(shù)據(jù)流ID,用來(lái)區(qū)分它屬于哪個(gè)數(shù)據(jù)流勾怒。另外還規(guī)定婆排,客戶端發(fā)出的數(shù)據(jù)流声旺,ID一律為奇數(shù),服務(wù)器發(fā)出的段只,ID為偶數(shù)腮猖。
數(shù)據(jù)流發(fā)送到一半的時(shí)候,客戶端和服務(wù)器都可以發(fā)送信號(hào)(RST_STREAM幀)赞枕,取消這個(gè)數(shù)據(jù)流澈缺。1.1版取消數(shù)據(jù)流的唯一方法,就是關(guān)閉TCP連接炕婶。這就是說(shuō)姐赡,HTTP/2 可以取消某一次請(qǐng)求,同時(shí)保證TCP連接還打開(kāi)著柠掂,可以被其他請(qǐng)求使用项滑。
客戶端還可以指定數(shù)據(jù)流的優(yōu)先級(jí)。優(yōu)先級(jí)越高涯贞,服務(wù)器就會(huì)越早回應(yīng)悟衩。
頭信息壓縮
HTTP 協(xié)議之前版本不帶有狀態(tài)藕施,每次請(qǐng)求都必須附上所有信息烧董。所以督暂,請(qǐng)求的很多字段都是重復(fù)的,比如Cookie和User Agent傻谁,一模一樣的內(nèi)容孝治,每次請(qǐng)求都必須附帶列粪,這會(huì)浪費(fèi)很多帶寬审磁,也影響速度。
HTTP/2 對(duì)這一點(diǎn)做了優(yōu)化岂座,引入了頭信息壓縮機(jī)制(header compression)态蒂。
一,頭信息使用gzip或compress壓縮后再發(fā)送
二费什,客戶端和服務(wù)器同時(shí)維護(hù)一張頭信息表钾恢,所有字段都會(huì)存入這個(gè)表,生成一個(gè)索引號(hào)鸳址,以后就不發(fā)送同樣字段了瘩蚪,只發(fā)送索引號(hào),這樣就提高速度了
服務(wù)器推送
HTTP/2 允許服務(wù)器未經(jīng)請(qǐng)求稿黍,主動(dòng)向客戶端發(fā)送資源疹瘦,這叫做服務(wù)器推送(server push)
常見(jiàn)場(chǎng)景是客戶端請(qǐng)求一個(gè)網(wǎng)頁(yè),這個(gè)網(wǎng)頁(yè)里面包含很多靜態(tài)資源巡球。正常情況下言沐,客戶端必須收到網(wǎng)頁(yè)后邓嘹,解析HTML源碼,發(fā)現(xiàn)有靜態(tài)資源险胰,再發(fā)出靜態(tài)資源請(qǐng)求汹押。其實(shí),服務(wù)器可以預(yù)期到客戶端請(qǐng)求網(wǎng)頁(yè)后起便,很可能會(huì)再請(qǐng)求靜態(tài)資源棚贾,所以就主動(dòng)把這些靜態(tài)資源隨著網(wǎng)頁(yè)一起發(fā)給客戶端了
注:可以看到,HTTP/2 協(xié)議相比之前版本先進(jìn)了很多榆综,更靈活鸟悴,更快速,更穩(wěn)定奖年,真的很期待全面普及的到來(lái)
本文若有任何的錯(cuò)誤請(qǐng)一定指出细诸,感謝
本文的歸納總結(jié)基于:
阮一峰 HTTP 協(xié)議入門(mén)
Hypertext Transfer Protocol -- HTTP/1.0