HTTP/0.9
HTTP協(xié)議是基于TCP/IP協(xié)議的應(yīng)用層協(xié)議葛虐,它不涉及數(shù)據(jù)包的傳輸罗售,只是規(guī)定了客戶端和服務(wù)器的通信格式锅劝,默認(rèn)使用80端口臀稚。
最早版本是1991年發(fā)布的0.9版本崭闲,改版本只有一個get命令
GET /index.html
上面命令表示在TCP鏈接建立之后請求網(wǎng)頁index.html
協(xié)議規(guī)定肋联,服務(wù)器只能回應(yīng)HTML格式的字符串,不能回一個別的格式刁俭,服務(wù)器發(fā)送完畢橄仍,TCP鏈接關(guān)閉。
HTTP/1.0
- 1996年5月http1.0發(fā)布
首先牍戚,任何格式的數(shù)據(jù)都可以發(fā)送侮繁,使得互聯(lián)網(wǎng)不僅可以傳輸圖像、視頻如孝、二進(jìn)制文件宪哩。
其次,除了GET命令之外第晰,還引入的POST命令和HEAD命令锁孟,豐富了瀏覽器和服務(wù)器的互動手段。
再次茁瘦,HTTP請求和回應(yīng)的格式也變了品抽,除了數(shù)據(jù)部分,每次通信都要包括頭信息甜熔,用來描述一些元數(shù)據(jù)圆恤。
其他的新增功能還包括狀態(tài)碼,多字符支持腔稀,多部分發(fā)送盆昙,權(quán)限,緩存焊虏,內(nèi)容編碼等弱左。 - 請求格式
下面是1.0版本的HTTP請求的例子。
GET/HTTP/1.0
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5)
Accept: */*
可以看到炕淮,這個格式和0.9版本有很大區(qū)別拆火,第一行是請求命令,必須在尾部添加協(xié)議版本,后面就是多行的頭信息们镜,描述客戶端情況
- 回應(yīng)格式
服務(wù)器的回應(yīng)如下
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
/n
<html>
<body>Hello World</body>
</html>
回應(yīng)的格式是"頭信息 + 一個空行(\r\n) + 數(shù)據(jù)"币叹。其中,第一行是"協(xié)議版本 + 狀態(tài)碼(status code) + 狀態(tài)描述"模狭。
-
Content-Type字段
關(guān)于字符串的編碼颈抚,1.0版本規(guī)定,頭信息必須是ASCII碼嚼鹉,后面的數(shù)據(jù)可以是任何格式贩汉,因此服務(wù)器在回應(yīng)的時候必須告訴客戶端,數(shù)據(jù)時什么格式锚赤,這就是Content-Type的作用匹舞,常見的Content-Type的值如下。- text/plain
- text/html
- text/css
- image/jpeg
- image/png
- text/svg+xml
- audio/mp4
- video/mp4
- application/javascript
- application/pdf
- application/zip
- application/atom+xml
這些數(shù)據(jù)類型總稱為MIME type线脚,每個值都包括一級類型和二級類型赐稽,中間用斜杠分割。
有了預(yù)定義的類型浑侥,廠商也可以自定義類型姊舵,
MIME Type也可以再尾部使用分號,添加參數(shù)寓落,
Content-Type:text/html;UTF-8
表明傳輸?shù)氖蔷W(wǎng)頁括丁,編碼是UTF-8.
客戶端請求的時候可以使用Accept字段表明自己可以接受哪些數(shù)據(jù)格式。Accept:*/*
這個表示伶选,客戶端聲明自己可以接受任何格式的數(shù)據(jù)躏将。
5. Content_Encoding字段
由于發(fā)送的數(shù)據(jù)可以是任何格式,因此可以吧數(shù)據(jù)壓縮之后再次進(jìn)行發(fā)送考蕾,Content-Encoding字段說明數(shù)據(jù)的壓縮方法。
```javascript
Content-Encoding: gzip
Content-Encoding: compress
Content-Encoding: deflate
客戶端在請求時会宪,用Accept-Encoding字段說明自己是可以接受哪些壓縮方法肖卧。
```javascript
Accept-Encoding: gzip, deflate
6. 缺點(diǎn)
http1.0的主要缺點(diǎn)是每個TCP鏈接只能發(fā)送一個請求,發(fā)送數(shù)據(jù)完畢掸鹅,就會關(guān)閉鏈接塞帐,如果還要請求其他數(shù)據(jù),就必須再新建其他的鏈接巍沙。
TCP的連接成本很高葵姥,需要進(jìn)行三次握手,并且開始時發(fā)送速率比較慢句携,所以HTTP1.0版本的姓名比較差榔幸。
為了解決這個問題,有些瀏覽器在請求時,會用一個非標(biāo)準(zhǔn)的Connection字段削咆。
```javascript
Connection: keep-alive
一個復(fù)用的TCP鏈接就建立 了牍疏,知道客戶端或者服務(wù)器主動關(guān)閉鏈接,但是這不是標(biāo)準(zhǔn)字段拨齐,不同實(shí)現(xiàn)的行為可能不一致鳞陨,因此這不是一個根本的解決方案。
HTTP1.1
持久鏈接
1.1最大的變化瞻惋,就是引入了持久連接厦滤,即TCP默認(rèn)不關(guān)閉,可以被多個請求復(fù)用歼狼,不用聲明Connection: keep-alive.
客戶端和服務(wù)器發(fā)現(xiàn)對方一段時間沒有活動掏导,就會主動關(guān)閉連接,但是規(guī)范的做法應(yīng)該是客戶端在最后一個請求是蹂匹,發(fā)送connection:close碘菜,明確服務(wù)器關(guān)閉TCP連接。
對于同一個域名限寞,大多數(shù)瀏覽器允許同事建立6個持久連接忍啸。管道機(jī)制
1.1版本還引入了管道機(jī)制,即在同一個TCp連接里面履植,客戶端可以同時發(fā)送多個請求计雌,進(jìn)一步解決了HTTP的效率問題。
舉例來說玫霎,客戶端需要請求兩個資源凿滤。以前的做法是,在同一個TCP連接里面庶近,先發(fā)送A請求翁脆,然后等待服務(wù)器做出回應(yīng),收到后再發(fā)出B請求鼻种。管道機(jī)制則是允許瀏覽器同時發(fā)出A請求和B請求反番,但是服務(wù)器還是按照順序,先回應(yīng)A請求叉钥,完成后再回應(yīng)B請求-
content-length
一個TCP鏈接現(xiàn)在是可以傳送多個回應(yīng)罢缸,這樣就需要有一個機(jī)制,區(qū)分?jǐn)?shù)據(jù)包是哪一個回應(yīng)的投队,這就是Content-length字段的作用枫疆,用來聲明本次回應(yīng)的數(shù)據(jù)長度。
Content-Length: 3495
上面的代碼就是告訴瀏覽器敷鸦,本次回應(yīng)的長度是3495個字節(jié)息楔,后面的字節(jié)就是屬于下一個回應(yīng)了寝贡。
在1.0版本中是不需要使用content-length字段的,因為瀏覽器發(fā)現(xiàn)服務(wù)器關(guān)閉了TCP連接钞螟,就 表示收到的數(shù)據(jù)已經(jīng)全了兔甘。
4. 分塊傳輸編碼
使用content-length的前提是,在服務(wù)器響應(yīng)之前鳞滨,必須知道響應(yīng)的數(shù)據(jù)長度洞焙。
對于一些很耗時的操作來說,意味著服務(wù)器要等到所有的操作完成之后才能發(fā)送數(shù)據(jù)拯啦,這樣效率不高澡匪,更好的處理方法是產(chǎn)生一塊數(shù)據(jù),就發(fā)送一塊褒链,使用“流模式”取代“緩存模式”唁情。
因此1.1版本規(guī)定可以不適用content-length字段,采用“分塊傳輸編碼”只要請求或回應(yīng)的頭信息有transfer-Encoding字段甫匹,就表示回應(yīng)的是長度未定的數(shù)據(jù)塊組成甸鸟。
```javascript
Transfer-Encoding: chunked
每個飛控數(shù)據(jù)塊之前,都會有一個16進(jìn)制的數(shù)值兵迅,表示這個塊的長度抢韭,最后是一個大小為0的塊,表示本次回應(yīng)的數(shù)據(jù)已經(jīng)發(fā)送完成了恍箭,如下例
```javascript
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
5. 其他功能
1.1版本還增加了許多動詞方法:PUT PATCH HEAD OPTIONS DELETE
另外客戶端請求的頭信息增加了Host字段刻恭,用來指定服務(wù)器的域名。
```javascript
Host: www.example.com
有了Host字段扯夭,就可以將請求發(fā)往同一個服務(wù)器的不同網(wǎng)站鳍贾,為虛擬主機(jī)打下了基礎(chǔ)。
- 缺點(diǎn)
隊頭阻塞:1.1雖然勻速復(fù)用TCP交洗,但是同一個TCP中骑科,所有的數(shù)據(jù)通信都是依次進(jìn)行,服務(wù)器只有處理完一個回應(yīng)才會進(jìn)行下一個回應(yīng)构拳。要是前面的響應(yīng)非常慢咆爽,后面就會有許多請求排隊等待
HTTP/2
- 二進(jìn)制協(xié)議
HTTP/1.1版的頭信息肯定是文本(ASCII編碼),數(shù)據(jù)體可以是文本也可以是二進(jìn)制隐圾,HTTP/2是一個徹底的二進(jìn)制協(xié)議,頭信息和數(shù)據(jù)體都是二進(jìn)制掰茶,并且統(tǒng)稱為“幀”暇藏,頭信息幀和數(shù)據(jù)幀。
二進(jìn)制幀的好處是可以定義額外的幀濒蒋,HTTP/2定義了近10中幀盐碱,也為將來的高級應(yīng)用打下了基礎(chǔ)把兔。 - 多工
HTTP/2 復(fù)用TCP連接,在一個連接里瓮顽,客戶端和瀏覽器都可以同時發(fā)送多個請求或回應(yīng)县好,而且不用按照順序一一對應(yīng),這樣就避免了"隊頭堵塞"暖混。
舉例來說缕贡,在一個TCP連接里面,服務(wù)器同時收到了A請求和B請求拣播,于是先回應(yīng)A請求晾咪,結(jié)果發(fā)現(xiàn)處理過程非常耗時,于是就發(fā)送A請求已經(jīng)處理好的部分贮配, 接著回應(yīng)B請求谍倦,完成后,再發(fā)送A請求剩下的部分泪勒。
這樣雙向的昼蛀、實(shí)時的通信,就叫做多工(Multiplexing)圆存。 - 數(shù)據(jù)流
因為 HTTP/2 的數(shù)據(jù)包是不按順序發(fā)送的叼旋,同一個連接里面連續(xù)的數(shù)據(jù)包,可能屬于不同的回應(yīng)辽剧。因此送淆,必 須要對數(shù)據(jù)包做標(biāo)記,指出它屬于哪個回應(yīng)怕轿。
HTTP/2 將每個請求或回應(yīng)的所有數(shù)據(jù)包偷崩,稱為一個數(shù)據(jù)流(stream)。每個數(shù)據(jù)流都有一個獨(dú)一無二的編號撞羽。數(shù)據(jù)包發(fā)送的時候阐斜,都必須標(biāo)記數(shù)據(jù)流ID,用來區(qū)分它屬于哪個數(shù)據(jù)流诀紊。另外還規(guī)定谒出,客戶端發(fā)出的數(shù)據(jù) 流,ID一律為奇數(shù)邻奠,服務(wù)器發(fā)出的笤喳,ID為偶數(shù)。
數(shù)據(jù)流發(fā)送到一半的時候碌宴,客戶端和服務(wù)器都可以發(fā)送信號(RST_STREAM幀)杀狡,取消這個數(shù)據(jù)流。1.1版取消數(shù)據(jù)流的唯一方法贰镣,就是關(guān)閉TCP連接呜象。這就是說膳凝,HTTP/2 可以取消某一次請求,同時保證TCP連接還打開著恭陡,可以被其他請求使用蹬音。
客戶端還可以指定數(shù)據(jù)流的優(yōu)先級。優(yōu)先級越高休玩,服務(wù)器就會越早回應(yīng)著淆。 - 頭信息壓縮
HTTP 協(xié)議不帶有狀態(tài),每次請求都必須附上所有信息哥捕。所以牧抽,請求的很多字段都是重復(fù)的,比如Cookie和User Agent遥赚,一模一樣的內(nèi)容扬舒,每次請求都必須附帶,這會浪費(fèi)很多帶寬凫佛,也影響速度讲坎。
HTTP/2 對這一點(diǎn)做了優(yōu)化,引入了頭信息壓縮機(jī)制(header compression)愧薛。一方面晨炕,頭信息使用gzip或compress壓縮后再發(fā)送;另一方面毫炉,客戶端和服務(wù)器同時維護(hù)一張頭信息表瓮栗,所有字段都會存入這個表,生成一個索引號瞄勾,以后就不發(fā)送同樣字段了费奸,只發(fā)送索引號,這樣就提高速度了进陡。 - 服務(wù)器推送
HTTP/2 允許服務(wù)器未經(jīng)請求愿阐,主動向客戶端發(fā)送資源,這叫做服務(wù)器推送(server push)趾疚。
常見場景是客戶端請求一個網(wǎng)頁缨历,這個網(wǎng)頁里面包含很多靜態(tài)資源。正常情況下糙麦,客戶端必須收到網(wǎng)頁后辛孵,解析HTML源碼,發(fā)現(xiàn)有靜態(tài)資源赡磅,再發(fā)出靜態(tài)資源請求魄缚。其實(shí),服務(wù)器可以預(yù)期到客戶端請求網(wǎng)頁后仆邓,很可能會再請求靜態(tài)資源鲜滩,所以就主動把這些靜態(tài)資源隨著網(wǎng)頁一起發(fā)給客戶端了。
HTTP method
- 一臺服務(wù)器要與HTTP1.1兼容节值,只要為資源實(shí)現(xiàn)GET和HEAD方法即可徙硅。
- GET是最常見的方法,通常用于請求服務(wù)器發(fā)送的某個資源
3.HEAD與GET類似搞疗,但服務(wù)器在響應(yīng)中只返回首部嗓蘑,不會返回實(shí)體的主體部分。 - PUT讓服務(wù)器用請求主體部分來創(chuàng)建一個由請求的REL命名的新文檔匿乃,如果那個URL已經(jīng)存在的話桩皿,就用這個主體替代。
- POST期初是用來向服務(wù)器輸入數(shù)據(jù)的幢炸,實(shí)際上用它來支持HTML表單泄隔,表單中填好的數(shù)據(jù)通常用被送給服務(wù)器,然后由服務(wù)器將其發(fā)送到要去的地方宛徊。
- TRACE會在目的服務(wù)器發(fā)起一個環(huán)回診斷佛嬉,最后一站的服務(wù)器會彈出一個TEACE響應(yīng)并在響應(yīng)主體中攜帶他收到的原始請求報文。TRANCE的方法主要用于診斷闸天,用于驗證請求是否如愿穿過了請求/響應(yīng)鏈暖呕。
- OPTIONS方法請求web服務(wù)器告知其支持的各種功能,可以查詢服務(wù)器支持哪些方法或者對某些特殊資源支持哪些方法苞氮。
- DELETE請求服務(wù)器刪除請求URL指定的資源湾揽。