HTTP概述
HTTP協(xié)議是什么
HTTP協(xié)議(HyperText Transfer Protocol),又稱超文本傳輸協(xié)議审胚,是網(wǎng)絡(luò)模型中應(yīng)用層的一個(gè)協(xié)議,通常被用來在一個(gè)服務(wù)端程序和客戶端程序間傳輸HTTP報(bào)文(下文會(huì)提到)礼旅,以達(dá)到傳輸HTML文件菲盾、圖片、視頻的效果各淀。
HTTP使用TCP作為它的支撐運(yùn)輸協(xié)議,這句話的意思是诡挂,HTTP協(xié)議本身并沒有傳輸?shù)牟糠炙榻剑鼉H僅是把需要傳輸?shù)膬?nèi)容封裝為HTTP數(shù)據(jù)報(bào),然后交給TCP協(xié)議去傳輸璃俗,由于TCP協(xié)議是一個(gè)可靠的協(xié)議奴璃,這也就意味著在一般情況下,一個(gè)客戶端進(jìn)程發(fā)出的HTTP請(qǐng)求總能完整的到達(dá)服務(wù)器城豁,反過來苟穆,我們也可以認(rèn)為在一般情況下服務(wù)器返回的HTTP報(bào)文也總能完整的到達(dá)發(fā)出響應(yīng)請(qǐng)求的客戶端。
HTTP是一個(gè)無狀態(tài)協(xié)議
HTTP是一個(gè)無狀態(tài)協(xié)議唱星,這句話的意思是說服務(wù)端程序在向客戶端程序發(fā)送文件時(shí)并不會(huì)存儲(chǔ)任何客戶端的狀態(tài)信息雳旅,這是有悖于我們的常識(shí)的,因?yàn)楝F(xiàn)在我們?cè)跒g覽網(wǎng)頁時(shí)大部分的信息都與賬戶信息有關(guān)(比如登陸電商網(wǎng)站去查看自己的購(gòu)物車數(shù)據(jù))间聊,但是在互聯(lián)網(wǎng)最初的時(shí)候大部分網(wǎng)頁都是靜態(tài)的攒盈,并不需要做任何與用戶信息相關(guān)的交互,但是隨著互聯(lián)網(wǎng)的發(fā)展哎榴,這種與用戶信息之間交互的需求越來越多型豁,開發(fā)人員就想到了在HTTP報(bào)文中添加一個(gè)叫做cookie的東西來解決這一問題僵蛛,但是我們?nèi)匀徽J(rèn)為HTTP協(xié)議是一個(gè)無狀態(tài)協(xié)議,因?yàn)橥ㄟ^cookie來返回相應(yīng)的數(shù)據(jù)是后端程序的任務(wù)迎变,與HTTP協(xié)議本身無關(guān)充尉。
HTTP的非持續(xù)連接和持續(xù)連接
非持續(xù)連接
非持續(xù)性鏈接即每一個(gè)連接只傳輸一個(gè)文件,比如我們?cè)L問百度首頁時(shí)除了要獲取百度首頁的html文件衣形,還要下載百度首頁的logo驼侠,如果采用非持續(xù)連接,將會(huì)產(chǎn)生兩個(gè)TCP傳輸通道泵喘,用來分別傳輸html文檔和圖片泪电。
我們知道TCP在連接時(shí)有一個(gè)三次握手和四次揮手的過程,這個(gè)過程會(huì)消耗一定的時(shí)間纪铺,在默認(rèn)情況下相速,一個(gè)瀏覽器能夠打開5~10個(gè)并行的TCP連接,當(dāng)請(qǐng)求的文件數(shù)大于該數(shù)目的時(shí)候鲜锚,頻繁的握手與揮手會(huì)導(dǎo)致時(shí)間上的損耗突诬。同時(shí)頻繁的創(chuàng)建與銷毀TCP連接也會(huì)帶來一些服務(wù)器性能上的損耗。
持續(xù)連接
持續(xù)連接即盡可能的復(fù)用客戶端與服務(wù)端的TCP連接芜繁,意思就是在傳輸完當(dāng)前的文件后不立即關(guān)閉該TCP連接旺隙,而是等待一段時(shí)間(可自由設(shè)置),如果在等待的時(shí)間內(nèi)再次收到客戶端的請(qǐng)求骏令,則繼續(xù)使用該TCP連接來進(jìn)行傳輸蔬捷。這樣一來就解決了非持續(xù)連接帶來的問題,但同時(shí)如果等待時(shí)間設(shè)置得不合理也會(huì)帶來許多問題榔袋,應(yīng)合理的設(shè)置等待的時(shí)間周拐。
HTTP報(bào)文
請(qǐng)求報(bào)文
一個(gè)典型的HTTP請(qǐng)求報(bào)文結(jié)構(gòu)如下圖所示
請(qǐng)求報(bào)文是由一行請(qǐng)求行和若干行首部行(headers)以及實(shí)體體(entity body,也有別的叫法叫請(qǐng)求體)組成凰兑,其中只有請(qǐng)求行是必須的妥粟,其他兩個(gè)在某些情況下并不一定會(huì)存在。
在linux下我們可以使用crul命令來查看HTTP的請(qǐng)求報(bào)文和響應(yīng)報(bào)文
我們使用
curl -v http://www.baidu.com/
命令來查看當(dāng)訪問百度時(shí)的HTTP請(qǐng)求報(bào)文吏够,部分返回結(jié)果如下所示請(qǐng)求行
請(qǐng)求行有三個(gè)字段勾给,分別是方法字段、URL字段和HTTP版本字段
方法字段
HTTP的方法包括GET锅知、POST播急、HEAD、PUT和DELETE五種售睹。
絕大多數(shù)的HTTP請(qǐng)求都使用的是GET方法旅择,當(dāng)我們?cè)跒g覽器中輸入一個(gè)網(wǎng)址得到相應(yīng)的網(wǎng)頁時(shí),也是使用的GET方法侣姆。
POST方法用來向服務(wù)器提交一些信息生真,比如說登陸時(shí)的用戶名和密碼沉噩,這些信息被保存在上面提到的實(shí)體體中,然后被傳輸?shù)椒?wù)器柱蟀。
HEAD方法與GET方法類似川蒙,它們的區(qū)別僅在于HEAD方法不會(huì)返回GET方法請(qǐng)求的對(duì)象(比如HTML文件),僅僅返回請(qǐng)求行和首部行长已。
PUT方法用來向服務(wù)器端上傳文件畜眨。
DELETE用來刪除服務(wù)器上的文件。
URL字段
即我們請(qǐng)求的文件在服務(wù)器中的位置术瓮,因?yàn)槲覀冞@里訪問的是百度的首頁康聂,默認(rèn)的就是根路徑,所以這里的URL字段為“/”胞四,如果我們使用curl -v http://www.baidu.com/index.php
恬汁,URL字段的值就會(huì)是"/index.php"
HTTP版本
傳輸使用的HTTP協(xié)議的版本,在這個(gè)示例中我們使用的是HTTP1.1
首部行
首部行中存儲(chǔ)著一些信息辜伟,多條首部行之間用回車符和換行符隔開氓侧,常見的如Host,用來表示請(qǐng)求訪問的主機(jī)名导狡、User-Agent约巷,用來表示發(fā)出客戶端請(qǐng)求的瀏覽器版本,由于我這里使用的是curl命令所以顯示的是curl
實(shí)體體
在上文中已經(jīng)提到過旱捧,存儲(chǔ)請(qǐng)求的信息独郎,但并不是每一個(gè)HTTP請(qǐng)求報(bào)文都有實(shí)體體
響應(yīng)報(bào)文
一個(gè)典型的HTTP響應(yīng)報(bào)文結(jié)構(gòu)如下圖所示
可以看出響應(yīng)報(bào)文的結(jié)構(gòu)與請(qǐng)求報(bào)文結(jié)構(gòu)很相似,僅僅是把請(qǐng)求行更改為了狀態(tài)行
同樣我們使用
curl -v http://www.baidu.com
命令查看該響應(yīng)報(bào)頭狀態(tài)行
版本
與請(qǐng)求報(bào)文相同枚赡,代表HTTP的版本
狀態(tài)碼與短語
狀態(tài)碼與短語是一一對(duì)應(yīng)的囚聚,它們結(jié)合起來共同反應(yīng)了請(qǐng)求的結(jié)果,下面是一些常見的狀態(tài)碼與短語以及它們所代表的含義
- 200 OK:請(qǐng)求成功标锄,信息在返回的響應(yīng)報(bào)文中
- 301 Moved Permanently:請(qǐng)求的對(duì)象已經(jīng)被永久轉(zhuǎn)移了,但是并沒有刪除茁计,該對(duì)象現(xiàn)在在服務(wù)器中的路徑會(huì)被放在響應(yīng)報(bào)文的Location:xxxxxxx首部行中料皇,以便于客戶端再次請(qǐng)求
- 400 Bad Request:一個(gè)通用的差錯(cuò)代碼,指該請(qǐng)求服務(wù)器不能理解
- 404 Not Found:請(qǐng)求的內(nèi)容在服務(wù)器上不存在
- 505 HTTP Version Not Support:服務(wù)器不支持請(qǐng)求所用的HTTP協(xié)議版本
首部行
響應(yīng)報(bào)文的首部行和請(qǐng)求報(bào)文的首部行作用基本一致星压,所以這里僅僅介紹幾個(gè)常見的響應(yīng)報(bào)文首部行的含義践剂。
- Connection:close/Keep-Alive 分別對(duì)應(yīng)上面說到的該HTTP使用非持續(xù)連接還是持續(xù)連接
- Date 服務(wù)器發(fā)送該響應(yīng)報(bào)文的時(shí)間
- Content-Length 響應(yīng)報(bào)文中實(shí)體體的長(zhǎng)度,單位是byte
- Content-Type 響應(yīng)報(bào)文返回的對(duì)象類型娜膘,可以看到這里返回的是一個(gè)html文檔或者普通文檔類型
- Last-Modified 該文件在服務(wù)器上最后被修改的時(shí)間逊脯,這一條我們最后在說代理服務(wù)器的時(shí)候會(huì)再次說到
- Server 響應(yīng)的服務(wù)器的名稱以及版本
代理服務(wù)器相關(guān)
如果所有的網(wǎng)絡(luò)請(qǐng)求都直接向其初始服務(wù)器發(fā)送的話,會(huì)給初始服務(wù)器帶來嚴(yán)重的負(fù)擔(dān)竣贪,此時(shí)我們需要在客戶端和服務(wù)端之間架設(shè)代理服務(wù)器來解決這一問題(如下圖所示)军洼。
它的工作原理是這樣的巩螃,客戶端發(fā)送的請(qǐng)求首先發(fā)送到代理服務(wù)器,如果代理服務(wù)器中存在客戶端想要的內(nèi)容匕争,那么代理服務(wù)器就可以把該內(nèi)容直接返回避乏,不需要向原始服務(wù)器發(fā)送請(qǐng)求,從而減少了初始服務(wù)器的負(fù)擔(dān)甘桑。以上的內(nèi)容可能比較抽象拍皮,下邊我們通過一個(gè)例子來分析。
假如我是第一次訪問百度的首頁跑杭,且代理服務(wù)器中沒有保存相關(guān)的對(duì)象铆帽,那么整個(gè)流程的順序是這樣的
- 客戶端向代理服務(wù)器發(fā)送請(qǐng)求表示自己要請(qǐng)求百度的主頁
- 代理服務(wù)器先檢查本地是否有百度的主頁,檢查后發(fā)現(xiàn)本地并沒有德谅,于是代理服務(wù)器向初始服務(wù)器發(fā)送請(qǐng)求向初始服務(wù)器索要相關(guān)的對(duì)象
- 初始服務(wù)器接受到請(qǐng)求把請(qǐng)求的對(duì)象返回給代理服務(wù)器
- 代理服務(wù)器接收到初始服務(wù)器返回的對(duì)象爹橱,在本地保存一份副本之后再將該對(duì)象返回給客戶端
- 客戶端收到代理服務(wù)器返回的數(shù)據(jù),在瀏覽器上顯示相應(yīng)的界面
從此之后我再訪問百度主頁女阀,整個(gè)流程就簡(jiǎn)單了很多宅荤,如下所示
- 客戶端向代理服務(wù)器發(fā)送請(qǐng)求表示自己要請(qǐng)求百度的主頁
- 代理服務(wù)器先檢查本地是否有百度的主頁,檢查后發(fā)現(xiàn)本地有百度首頁的文件浸策,將該對(duì)象返回給客戶端
- 客戶端收到代理服務(wù)器返回的數(shù)據(jù)冯键,在瀏覽器上顯示相應(yīng)的界面
但是這樣就導(dǎo)致了一個(gè)問題,就是如果服務(wù)器上的文件在代理服務(wù)器保存之后進(jìn)行了更改怎么辦庸汗,這時(shí)就需要用到我們上面說到的Last-Modified首部行惫确,當(dāng)代理服務(wù)器接受到請(qǐng)求時(shí),它向初始服務(wù)器發(fā)送一個(gè)請(qǐng)求去對(duì)比本地文件的Last-Modified與服務(wù)器上的Last-Modified是否一致蚯舱,如果一致就直接將本地的對(duì)象返回改化,如果不一致就再次從初始服務(wù)器下載一份覆蓋掉本地對(duì)象,再將該對(duì)象返回給客戶端枉昏。