首先我們來了解一下什麼是HTTP協議
HTTP:HyperText Transfer Protocol,中文超文字傳輸協議;
顧名思義,主要就是用於傳輸超文字的,相當於一條海上運輸的賊船。
超文字:指的是帶有超級連結的文字,相當於這條賊船運輸的特殊貨物,這些貨物是什麼呢,是任意門。
超連結:基於此種連結能夠在文件間實現跳轉,也就是能通向其他空間的任意門。
http/0.9
在當時,http協議廣泛應用的版本為0.9,那個時候的Web服務僅支援純文字(純文字:由純ASCII字元組成的文字),這種純文字還包括超連結,這種超連結也是表現為純文字形式的,但這種文字比較獨特,因此稱為超文字(HTML)。
HTML:HyperText Mark Language,超文字標記語言;這是用於編寫(開發)超文字的語言
之所以叫標記語言是因為在這種語言當中事先規定好了將語言透過標籤的形式給它加上一些特殊的標記,而這些文字在被使用者客戶端瀏覽器解析時能夠將這些標記解析為字型格式或一些表現屬性,如:Title。通俗的比喻,HTML是暗號,每個暗號都有一段特殊含義,例如:某些交易行業有一些暗語,“‘空’是有空的意思,‘路’是在路上,‘見’是見到了客人,‘喜’是被客人看上了,‘收’是完成交易收款,‘回’是返回。”
Browser:瀏覽器,客戶端代理的一種,透過http協議可以訪問伺服器端提供的超文字,而Browser能夠在這些文字顯示的時候將標籤解析為對應的修飾的屬性格式。相當於暗語翻譯機。
當Web服務流行開來之後,全球能夠提供Web服務的伺服器有很多個,那麼每一臺伺服器上都可以提供各種各樣的文字,甚至於兩臺伺服器上提供的文字的名字可能是一樣的。就好像流行給每個人取名字以後,大家都會爭相給娃取名字,於是像張傑、張偉這樣的名字遍佈全國各地,那麼如果要去民政局登記結婚,怎麼區分是山東的張偉和李小姐結婚了還是湖北的張偉呢?
因此僅靠檔名進行區分文件是不可靠的。於是就出現了向URI這樣的機制(雖然URI並不是專門為Web誕生的),URI是很好的能夠讓客戶端識別網際網路上不同文件的機制。
URI:Uniform Resource Indientifier,統一資源識別符號;
用於定義全域性範圍內標記唯一的定位一種資源訪問路徑的方式(命名方式);(不一定是網際網路上的,全球的,包括網際網路在內的可以在全域性唯一引用某一個獨立的資源的命名方式)
統一資源標誌符URI就是在某一規則下能把一個資源獨一無二地標識出來。還是用取名字做例子,假設這個世界上所有人的名字都不能重複,那麼名字就是URI的一個例項,透過名字這個字串就可以標識出唯一的一個人。現實當中名字當然是會重複的,所以身份證號才是URI,透過身份證號能讓我們能且僅能確定一個人。
URL:Uniform Resource Locator,統一資源定位符(URI的子物件、子集)
用於描述在網際網路上網際網路資源的統一表示格式。
也拿人做例子然後跟HTTP的URL做類比,就可以有:人物住址協議://地球/中國/湖北省/武漢市/洪山區/某道路/某樓棟/403號辦公室/張偉.人可以看到,這個字元串同樣標識出了唯一的一個人,起到了URI的作用,所以URL是URI的子集。URL是以描述人的位置來唯一確定一個人的。在上文我們用身份證號也可以唯一確定一個人。對於這個在武漢的張偉,我們也可以用身份證號:123456789來標識他。所以不論是用定位的方式還是用編號的方式,我們都可以唯一確定一個人,都是URl的一種實現,而URL就是用定位的方式實現的URI。
回到Web上,假設所有的Html文件都有唯一的編號,記作html:xxxxx,xxxxx是一串數字,即Html文件的身份證號碼,這個能唯一標識一個Html文件,那麼這個號碼就是一個URI。而URL則透過描述是哪個主機上哪個路徑上的檔案來唯一確定一個資源,也就是定位的方式來實現的URI。
格式:protocol://HOST:port/path/to/file
HTTP方法:(獲取資源的方式)
http/0.9時只有一個方法:
GET,它表示直接從伺服器上獲取文件到本地瀏覽器並予以展示(不是簡單的檔案傳輸,而是超文字的檔案傳輸);
在http升級到1.0之後有了更多的方法:
PUT:從遠端伺服器上直接獲取檔案到本地,與POST相對應
POST:與GET相對應,透過表單提交資料到伺服器上去;
DELETE:在遠端伺服器上刪除檔案,與PUT相對應;
HEAD:只返回首部,不響應主體;
簡單來說,get是七八十年代實打實的透過相親方式認識接觸的女朋友;而科技發展了以後我們有了手機,put是從聊天軟體諸如momo、tantan這樣的應用裡撩到的女朋友;有了女朋友你得給她花錢了吧,所以post是陪女朋友逛街給她買單;delete就是在聊天軟體上你和“女朋友”聊的不爽了要分手,你就把她刪除拉黑了。
對於伺服器來講,PUT、POST、DELETE都不安全,因為它們都允許客戶端直接操作伺服器上的資源,因此一般來講,需要透過認證以後才能允許客戶端操作。最安全的方法就是GET,GET類似於只讀的意思。
MIME機制:
HTTP1.0更大的改進之處就是引入了MIME機制:
MIME:Multipurpose Internet Mail Extension,多功能(用途)網際網路擴充套件郵件;
MIME實現了能夠將非文字(如:二進位制)資料在傳輸前重新編碼為文字格式再進行傳輸,接收方能夠用相反的方式將其重新還原成原來的格式,還能夠呼叫相應的程式開啟此檔案。如:傳輸過去一個rar檔案,對方知道這是一個rar壓縮包並且能夠用相應的軟體開啟;若傳輸的是圖片就能呼叫程式開啟圖片。所以在MIME編碼當中,Base64就是一種文字編碼格式。
SMTP:Simple Mail Transfer Protocol,簡單郵件傳輸協議;
郵件傳輸協議早期只能傳輸純文字,但後來不僅可以傳輸純文字,還可以傳輸圖片、影片等二進位制檔案,因為後來引入了MIME機制。
在http1.0協議當中,也是純文字傳輸的,後來參照了SMTP的純文字傳輸機制將MIME引入到了http協議當中,從此以後,http協議也可以傳輸非文字資料了。
實現過程:在客戶端去獲取某個資源時,資源傳遞到客戶端時,明確說明是哪一類檔案,如:是一個image/jpeg格式的圖片,透過http協議的元資料(協議首部),在協議首部裡邊明確新增一個首部,告訴對方自己的檔案是image/jpeg格式,所以客戶端發現這是一個image大類下的jpeg小子類。此時,瀏覽器呼叫內部與之相匹配的外掛來展示這個檔案。若瀏覽器不支援這種外掛,可以透過介面呼叫外部的系統上安裝的其它的能夠顯示檔案的外掛,以外掛的機制在瀏覽器中去解析對應MIME格式的文件的。因此我們可以發現若未安裝flash外掛,開啟網頁後許多flash外掛是無法顯示的也正是基於此種原理。當然,也正是這種外掛機制的實現,使得後來出現了動態網頁的技術。
動態效果:
如:Java,Applet,JRE。嵌入到網頁中,透過http協議傳輸到客戶端,透過JRE環境展示動態效果,但由於過於重量級,在與flash的競爭中落敗。
動態網頁:
動態網頁指的就是在伺服器端儲存的使用者訪問的文件不再是HTML格式,而是程式語言開發的指令碼(也可以是非指令碼)。這個指令碼在接收引數之後在伺服器執行一次,執行完成之後會生成HTML格式的文件,並且把生成的文件傳送給客戶端。需要注意的是,這個程式語言所開發的指令碼在使用者訪問時不是原封不動的傳送給客戶端,而是要先獲取客戶端的特性(客戶端獲取資源時需要先發起申請,而在發起申請之前需要把客戶端地址、客戶端瀏覽器的型別等一併傳送給伺服器),伺服器獲取客戶端地址,瀏覽器型別等資料並將這些資料當做引數傳遞給指令碼,讓指令碼在伺服器端執行一次。因此任何一個使用者去訪問,都是根據使用者的特性隨時生成的,所以稱為動態網頁。
http請求在伺服器端處理的過程詳細描述:(請求分別為靜態網頁與動態網頁時的情況)
首先我們需要確定的是Web伺服器是一個程序,這個程序在使用者空間(Web伺服器是一個特殊的具體應用,而既然是具體應用那就是一個具體的軟體,那麼這個軟體就應該放在使用者空間)。而使用者所有能夠訪問的網頁檔案都存放在磁碟上,因此客戶端向伺服器發起請求時,這個請求先到達核心空間,而又因為這個客戶端請求一定是透過網路協議傳送過來的,而協議工作在核心(TCP/IP協議在核心工作),所以首先到達核心,核心空間解析接收到請求後,在核心中透過TCP/IP協議棧中各種路由機制(編碼)等發現這個請求訪問的是本機地址80埠的套接字,因為Web服務一旦啟動之後一定會監聽在TCP協議的80埠之上,因此核心就將請求透過套接字轉交給使用者空間的Web伺服器,因此執行流程就從核心空間轉到了使用者空間了。
若Web伺服器發現使用者訪問的是一個檔案,如:index.html,此時伺服器就得陷入到核心中,重新轉換為核心模式,到磁碟上將檔案載入過來,核心找到這個檔案後再返回給使用者空間,此時又回到了Web伺服器了,Web伺服器發現這個檔案取出來了就可以響應客戶端了。此時再透過套接字回到核心空間,透過網路TCP/IP協議棧最終響應給客戶端。
如果使用者訪問的是動態網頁,就不能直接予以響應了,需要透過其它協議啟動另外一個程序,這個程序一定是一個直譯器,如bash指令碼就是bash直譯器,PHP指令碼就是PHP直譯器。然後透過協議將這個檔案傳遞給這個直譯器或者這個直譯器能夠訪問這個文件直譯器自己陷入到核心模式將文件讀取到直譯器中,在解釋其中執行一次,將執行結果返回給Web伺服器。
Web伺服器將請求的結果透過網路傳遞給客戶端,它需要額外啟動一個程序,程序和伺服器之間建立的聯絡是透過協議實現的,而在這個程序執行結束後需要銷燬。所以對於Web伺服器來講,若要響應一個動態內容,需要先建立一個新的子程序,這個程序執行一次結束後需要將這個程序銷燬,而這都是系統資源開銷,對於一個客戶端訪問可能無所謂,但成千上萬的客戶端訪問呢?因此我們可以推斷到響應動態內容伺服器需要更多的系統資源。
在一個HTML網頁中,可能會透過超連結引用n個資源(Web物件),而這n個web物件每一個都有自己的URL。而動態網頁生成的HTML結果中也可以引用web物件,這些web物件是靜態的,所以動態網頁包含:靜態內容(無需改變或無需執行的內容如:圖片、檔案、rar壓縮包)和動態內容(需要執行一次才能返回給客戶端,只有動態內容才需要執行)。在http1.0之後就能支援這些機制了,正是1.0中引入了MIME,使得Web服務對於多媒體的支援得到了極大的擴充套件,也正是1.0系列的出現,使得web伺服器迅速流行開來並大大的促進了網際網路的發展。
我們再來詳細討論一下整個過程:
以純靜態頁面來講,所有使用者訪問的內容都是一樣的,由此我們來分析一個問題:
一個客戶端發起Web服務請求到伺服器需要經過多少個層次呢?如在瀏覽器輸入一個url訪問,第一步需要把FQDN轉換成IP地址,因此在請求發出之前需要先透過DNS伺服器解析FQDN,而DNS伺服器可能會遞迴、迭代,需要消耗一些時間(在第一次訪問時,記錄未快取到本地),之後客戶端輸入地址傳送請求給伺服器,伺服器接收請求後,在內部需要有一個機制能夠接收使用者的請求,這種機制就叫做監聽,監聽在某個埠上,等待客戶端的請求。
一旦使用者請求來了,而核心透過TCP/IP協議棧發現有人監聽在這個埠上,於是這個請求就可以交給這個套接字了。但如果本地沒有任何一個使用者程序監聽在某個套接字,但有客戶端來訪問了,此時核心無法知道有誰能夠響應這個請求,此時就會拒絕客戶端請求,如:此地未啟動這個服務,因此必須到核心中去註冊需要使用哪一個埠並一直在這個埠上處於等待狀態。所以當有請求到來時,透過TCP/IP協議的首部解碼後發現使用者訪問的是這麼一個埠,於是就把這個請求轉交給這個埠,而程序又一直監聽在這個埠,一旦有請求來了,可進行響應。
http報文:
TCP/IP協議在封裝報文時,TCP首部主要是源埠(Source Port)、目標埠(Destination Port),IP首部主要是源IP地址(Source IP)、目標IP地址(Destination IP)。但卻並沒有明確說明具體訪問哪個文件或資源,因此某一特定的應用在透過TCP/IP協議往外發送時,TCP/IP最多就是將報文傳遞到目的地,到達目的地後還需要具體協議的報文首部。因此http協議也有自己的首部,叫http首部,它明確定義了基於哪種協議獲取哪個資源的,需要說明獲取什麼文件,
如:GET /2.html,並且還需要說明獲取哪個主機的資源,因此通常還有一個首部叫:Host 加主機是HTTP1.0中引入的一種機制,在發起獲取資源請求時,不但要指明獲取哪個資源,還要再加上獲取哪個主機的資源,這個主機一定是主機名稱,這是為虛擬主機做準備的)。說白了,這一切就叫http報文。
IP:
Source IP
Destination IP
TCP:
Source Port
Destination Port
http首部:
GET/2.html
http報文分為兩種:請求報文、響應報文。
報文語法:
上面兩個報文的第一行稱為報文"起始行(start line)";後面的標籤格式的內容稱作首部域(Header field),每個首部域都由名稱(name)和值(value),中間用逗號分隔,另外,響應報文通常還有一個稱作Body的資訊主體,即響應給客戶端的內容。
請求報文:
method:資源獲取方法;
request-URL:請求的資源是什麼;
version:對應請求資源協議的版本號;
headers:http協議首部;
headers後的空白行是必須的;
entity-body:空白行後有一些報文主體(報文內容)
響應報文:
version:對應請求的版本
status:狀態(代)碼,請求結果正確與否的識別符號
狀態碼分為5類:
1xx:純資訊,與請求的資源沒有太大的關係;
2xx:“成功”類的狀態碼資訊,常用狀態碼:200(表示請求資源正常,已獲取到正常響應);
3xx:重定向類的資訊,表示請求的資源已存在,但資源已被挪到其它地方了,如:給了一個參考答案說這個資源已經被挪走了,請重新發起請求另外一個地址,並且把另外的參考地址也響應給客戶端了。常用的狀態碼:301(表示永久重定向,永久的挪到了那個位置了)、302(臨時重定向,繁忙時重定向到指定位置尋找)、304(表示請求的內容未發生任何改變,若快取過直接使用快取即可)。需要注意的是,重定向的資訊未必都是重定向,如304狀態碼;
4xx:客戶端錯誤類資訊,常用狀態碼:404(請求了一個不存在的檔案);
5xx:伺服器端錯誤類資訊;
reason-phrase:定義解釋status的意義;
headers:響應報文首部;
entity-body:報文主體;
報文舉例:
GET/HTTP/1.1中的/表示訪問一個網站但沒有明確指定訪問哪個頁面,/表示訪問對方的預設頁面(主頁)。
快取:在http/1.0中,引入快取的機制時為了加速系統訪問、節省網路頻寬的。
http協議基於TCP協議,每一個TCP的建立都需要3次握手,而拿到資源後需要4次斷開。為了避免每一次訪問資源都要三次握手、四次揮手,推出了http/1.1。
http/1.1:
增強了快取功能;
引入了長連線;
獲取資源後並不是立即斷開連線,而是繼續獲取下一個資源;而長連線可以讓同一個客戶端發起第二個請求時儘可能縮短時間也降低伺服器端資源佔用率,但是當伺服器端頻寬佔用巨大時,後來的客戶端可能很難建立連線了。
因此,為了資源的有效利用不能讓建立長連線的客戶端永久線上,因此給出兩個限定:1.若請求第一或第二個資源後就不再請求,需要定義一個超時時間,到達一定時間後超時斷開;2.當一直請求不斷開時,定義做多請求多少次,如還請求,需要重新排隊。