1. 什么是HTTP協議?
HTTP協議是Hyper Text Transfer Protocol(超文本傳輸協議)的縮寫,是用於從萬維網(WWW:World Wide Web )服務器傳輸超文本到本地瀏覽器的傳送協議。
RFC 1945定義了HTTP/1.0版本。其中最著名的就是RFC 2616。RFC 2616定義了今天普遍使用的一個版本——HTTP 1.1。
簡單地說,我們上網就是用戶(客戶端)遵循該協議向服務器發送請求獲取資源,服務器解析該協議知道用戶請求什么,然后把結果返回。
2. HTTP協議的內容?
HTTP是基於傳輸層的TCP協議,而TCP是一個端到端的面向連接的協議。所以HTTP在開始傳輸之前,首先需要建立TCP連接,而TCP連接的過程需要所謂的“三次握手”。下圖所示TCP連接的三次握手。
在TCP三次握手之后,建立了TCP連接,此時HTTP就可以進行傳輸了。一個重要的概念是面向連接,既HTTP在傳輸完成之間並不斷開TCP連接。在HTTP1.1中(通過Connection頭設置 keep alive)這是默認行為。
簡單地說,三次握手就是去小餐廳點菜,會先問我能點菜嗎?可以,你確定要點餐嗎?我確定要點餐。我要點吧啦吧啦……開始寫菜單
2.1 客戶端使用HTTP協議給服務器發送了什么?
HTTP請求由狀態行、請求頭、請求體三部分組成:
請求行:
①是請求方法,GET和POST是最常見的HTTP方法,除此以外還包括DELETE、HEAD、OPTIONS、PUT、TRACE、CONNECT,一共八種。
②為請求對應的URL地址,它和報文頭的Host屬性組成完整的請求URL。
③是協議名稱及版本號。
請求頭:
④是HTTP的報文頭,報文頭包含若干個屬性,格式為“屬性名:屬性值”,服務端據此獲取客戶端的信息。
與緩存相關的規則信息,均包含在header中
請求體:
⑤是報文體,它將一個頁面表單中的組件值通過param1=value1¶m2=value2的鍵值對形式編碼成一個格式化串,它承載多個請求參數的數據。不但報文體可以傳遞請求參數,請求URL也可以通過類似於“/chapter15/user.html? param1=value1¶m2=value2”的方式傳遞請求參數。
簡單來說,就是下菜單,點菜,寫備注寫要求。
2.2 服務器使用HTTP協議給客戶端返回了什么?
HTTP的響應報文也由三部分組成,分別是響應行、響應頭、響應體。
響應行:
①報文協議及版本;
②狀態碼及狀態描述;
響應頭:
③響應報文頭,也是由多個屬性組成;
響應體:
④響應報文體,即我們真正要的“干貨”。
響應狀態碼:
和請求報文相比,響應報文多了一個“響應狀態碼”,它以“清晰明確”的語言告訴客戶端本次請求的處理結果。
HTTP的響應狀態碼由5段組成:
(1)1xx 消息,一般是告訴客戶端,請求已經收到了,正在處理,別急...
(2)2xx 處理成功,一般表示:請求收悉、我明白你要的、請求已受理、已經處理完成等信息。
(3)3xx 重定向到其它地方。它讓客戶端再發起一個請求以完成整個處理。
(4)4xx 處理發生錯誤,責任在客戶端,如客戶端的請求一個不存在的資源,客戶端未被授權,禁止訪問等。
(5)5xx 處理發生錯誤,責任在服務端,如服務端拋出異常,路由出錯,HTTP版本不支持等。
常見的狀態碼:
200 OK 請求成功;
302 臨時重定向
304 Not Modified 請求內容沒有修改,使用本地緩存啦...
404 Not Found 請求的資源不存在
500 Internal Server Error 服務器錯誤
3. HTTP的無狀態特點
根據早期的HTTP協議,每次請求響應時,都要重新建立TCP連接。TCP連接每次都重新建立,所以服務器無法知道上次請求和本次請求是否來自於同一個客戶端。因此,HTTP通信是無狀態(stateless)的。服務器認為每次請求都是一個全新的請求,無論該請求是否來自同一地址。
問題:為什么登錄后就不用登錄了?這不是記錄的狀態了嗎?
答:HTTP並沒有記錄狀態,而是程序,如PHP程序把狀態保存在了cookie,session,不是HTTP記錄了。
1. HTTP版本更替
HTTP/0.9
HTTP協議的最初版本,功能簡陋,僅支持請求方式GET,並且僅能請求訪問HTML格式的資源。
HTTP/1.0
在0.9版本上做了進步,增加了請求方式POST和HEAD;不再局限於0.9版本的HTML格式,根據Content-Type可以支持多種數據格式,即MIME多用途互聯網郵件擴展,例如text/html、image/jpeg等;同時也開始支持cache,就是當客戶端在規定時間內訪問統一網站,直接訪問cache即可。
但是1.0版本的工作方式是每次TCP連接只能發送一個請求,當服務器響應后就會關閉這次連接,下一個請求需要再次建立TCP連接,就是不支持keepalive。
HTTP/1.1
解決了1.0版本的keepalive問題,1.1版本加入了持久連接,一個TCP連接可以允許多個HTTP請求; 加入了管道機制,一個TCP連接同時允許多個請求同時發送,增加了並發性;新增了請求方式PUT、PATCH、DELETE等。
但是還存在一些問題,服務端是按隊列順序處理請求的,假如一個請求處理時間很長,則會導致后邊的請求無法處理,這樣就造成了隊頭阻塞的問題;同時HTTP是無狀態的連接,因此每次請求都需要添加重復的字段,降低了帶寬的利用率。
HTTP/2.0
為了解決1.1版本利用率不高的問題,提出了HTTP/2.0版本。增加雙工模式,即不僅客戶端能夠同時發送多個請求,服務端也能同時處理多個請求,解決了隊頭堵塞的問題;HTTP請求和響應中,狀態行和請求/響應頭都是些信息字段,並沒有真正的數據,因此在2.0版本中將所有的信息字段建立一張表,為表中的每個字段建立索引,客戶端和服務端共同使用這個表,他們之間就以索引號來表示信息字段,這樣就避免了1.0舊版本的重復繁瑣的字段,並以壓縮的方式傳輸,提高利用率。
另外也增加服務器推送的功能,即不經請求服務端主動向客戶端發送數據,例如服務端可以主動把 JS 和 CSS 文件推送給客戶端,而不需要客戶端解析 HTML 再發送這些請求,當客戶端需要的時候,它已經在客戶端了。
當前主流的協議版本還是HTTP/1.1版本,既然HTTP/2.0這么好,為什么主流還是HTTP/1.1呢?
原因有很多:
(1)設備問題,以前的舊手機系統很多不支持。
(2)成本問題,HTTP/2.0開啟https,就需要證書,購買證書需要花費。
(3)技術、運維成本,HTTPS部署相對HTTP來說麻煩好多。而且,如果正在使用HTTP,再轉HTTP2,就可能需要替換時間成本。
(4)開發語言不支持,目前主流的開發語言,如C/C++,java,php等等都支持,但是有個別小眾的語言應該還不支持。
(5)目前網站速度可以,不想更換。
(6)……