楠木軒

HTTP是什麼?是怎麼發展的?

由 圖門耘 發佈於 科技

首先我們來了解一下什麼是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.當一直請求不斷開時,定義做多請求多少次,如還請求,需要重新排隊。