在互聯網時代HTTP協議的重要性無需多言,對於技術崗位的同學們來說理解掌握HTTP協議是必須的。本篇博客就從HTTP協議的演進、特性、重要知識點和工作中常見問題的總結等方面進行簡單的介紹。理解掌握了這些點工作中就OK了,當然在面試中也是少不了的,如果能結合實踐掌握這篇博客的80%應對一般的面試應該是夠了。如果要深入學習HTTP協議的細節請看那本經典的《HTTP權威指南》。
一、HTTP協議的演進
HTTP(HyperText Transfer Protocol)協議是基於TCP的應用層協議,它不關心數據傳輸的細節,主要是用來規定客戶端和服務端的數據傳輸格式,最初是用來向客戶端傳輸HTML頁面的內容。默認端口是80。關於HTTP協議歷史演進的詳細介紹請參考:http://www.ruanyifeng.com/blog/2016/08/http.html
1.HTTP 0.9版本 1991年
這個版本就是最初用來向客戶端傳輸HTML頁面的,所以只有一個GET命令,然后服務器返回客戶端一個HTML頁面,不能是其他格式。利用這個版本完全可以構建一個簡單的靜態網站了。
2.HTTP 1.0版本 1996年
1.0版本是改變比較大的,奠定了現在HTTP協議的基礎。這個版本的協議不僅可以傳輸HTML的文本頁面,還可以傳輸其他二進制文件,例如圖片、視頻。而且還增加了現在常用的POST和HEAD命令。請求消息和響應消息也不是單一的了,規定了一些元數據字段。例如字符集、編碼、狀態響應碼等。
3.HTTP 1.1版本 1997年
實際上是在1.0版本之后半年時間又發布了一個版本,這個版本在1.0版本的基礎上更加完善了。這個版本增加了持久連接,就是說之前版本的協議一次請求就是一次TCP連接,請求完成后這個連接就關閉掉了。眾所周知TCP協議是可靠的,建立連接需要3次握手,斷開連接需要4次揮手,並且TCP有流量控制和擁塞控制,有慢開始機制,剛建立連接時傳輸比較慢,這是比較耗費資源的。一個豐富的頁面會有許多圖片、表單和超鏈接。這樣的話就會有多次的HTTP請求,所以在這個版本上默認不關閉TCP連接也不用聲明Connection: keep-alive字段。如果確實要關閉可以指定Connection: close字段。還引入了管道機制,就是說在一個TCP連接里可以同時發送多個HTTP請求,而不必等待上一個請求響應成功再發送。還增加了PUT、PATCH、HEAD、 OPTIONS、DELETE等命令,豐富了客戶端和服務端交互動作。還增加了Host字段。
4.HTTP 2版本 2015年
這個版本也是隨着互聯網的發展,有了新的需求制定了新的功能還有對上一個版本的完善。1.1版本有了管道機制,但是正在服務端還是要對請求進行排隊處理。這個版本可以多工的處理。還有了頭信息壓縮和服務器的主動推送。
5.HTTPS
HTTPS是HTTP協議的安全版本,HTTP協議的數據傳輸是明文的,是不安全的,HTTPS使用了SSL/TLS協議進行了加密處理。
二、HTTP協議的特點(下面介紹沒有特殊說明默認HTTP/1.1版本)
1.HTTP協議是無狀態的
就是說每次HTTP請求都是獨立的,任何兩個請求之間沒有什么必然的聯系。但是在實際應用當中並不是完全這樣的,引入了Cookie和Session機制來關聯請求。
2.多次HTTP請求
在客戶端請求網頁時多數情況下並不是一次請求就能成功的,服務端首先是響應HTML頁面,然后瀏覽器收到響應之后發現HTML頁面還引用了其他的資源,例如,CSS,JS文件,圖片等等,還會自動發送HTTP請求這些需要的資源。現在的HTTP版本支持管道機制,可以同時請求和響應多個請求,大大提高了效率。
3.基於TCP協議
HTTP協議目的是規定客戶端和服務端數據傳輸的格式和數據交互行為,並不負責數據傳輸的細節。底層是基於TCP實現的。現在使用的版本當中是默認持久連接的,也就是多次HTTP請求使用一個TCP連接。
三、HTTP報文
1.請求報文
舉例:

GET /wxisme HTTP/1.1 Host: www.cnblogs.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.0; zh-CN; rv:1.8.1) Gecko/20061010 Firefox/2.0 Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 Accept-Language: en-us,zh-cn;q=0.7,zh;q=0.3 Accept-Encoding: gzip,deflate Accept-Charset: gb2312,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Proxy-Connection: keep-alive Cookie: ASP.NET_SessionId=ey5drq45lsomio55hoydzc45 Cache-Control: max-age=0
簡單來說請求報文就是由請求行(開始行)、請求頭(首部行)、內容實體組成的,注意,每一行的末尾都有回車和換行,在內容實體和請求頭之間另有一個空行。其中請求行指定的是請求方法、請求URL、協議版本;請求頭是鍵值對的形式存在的;內容實體就是要傳輸的數據。稍后會對方法、請求頭字段做詳細的說明。
2.響應報文
舉例:
HTTP/1.1 200 OK Date: Tue, 12 Jul 2016 21:36:12 GMT Content-Length: 563 Content-Type: text/html <html> <body> Hello http! </body> </html>
簡單來說響應報文由狀態行、響應首部字段(響應頭)、響應實體組成,其中第一行是狀態行,依次包含HTTP版本,狀態碼和狀態短語組成;在一個回車換行之后是響應頭,也是鍵值對的形式;然后會有一個空行也包含回車換行,之后是響應實體,就是要傳輸的數據。在上面的例子當中就是一個非常簡單的HTML頁面。對於響應狀態碼,首部字段鍵值對稍后會有更加詳細的說明。
四、HTTP請求方法
請求方法是客戶端用來告知服務器其動作意圖的方法。就像下達命令一樣。在HTTP1.1版本中支持GET、POST等近10種方法。需要注意的是方法名區分大小寫,需要用大寫字母。下面詳細說明。
1.GET:獲取資源,GET方法用來請求訪問已被URI識別的資源。也就是指定了服務器處理請求之后響應的內容。
2.POST:傳輸實體主體,POST方法用來傳輸實體主體。POST與GET的區別之一就是目的不同,二者之間的區別會在文章的最后詳細說明。雖然GET方法也可以傳輸,但是一般不用,因為GET的目的是獲取,POST的目的是傳輸。
3.PUT:傳輸文件,PUT方法用來傳輸文件。類似FTP協議,文件內容包含在請求報文的實體中,然后請求保存到URL指定的服務器位置。
4.HEAD:獲得報文首部,HEAD方法類似GET方法,但是不同的是HEAD方法不要求返回數據。用於確認URI的有效性及資源更新時間等。
5.DELETE:刪除文件,DELETE方法用來刪除文件,是與PUT相反的方法。DELETE是要求返回URL指定的資源。
6.OPTIONS:詢問支持的方法,因為並不是所有的服務器都支持規定的方法,為了安全有些服務器可能會禁止掉一些方法例如DELETE、PUT等。那么OPTIONS就是用來詢問服務器支持的方法。
7.TRACE:追蹤路徑,TRACE方法是讓Web服務器將之前的請求通信環回給客戶端的方法。這個方法並不常用。
8.CONNECT:要求用隧道協議連接代理,CONNECT方法要求在與代理服務器通信時建立隧道,實現用隧道協議進行TCP通信。主要使用SSL/TLS協議對通信內容加密后傳輸。
五、HTTP的響應狀態碼
狀態碼是用來告知客戶端服務器端處理請求的結果。憑借狀態碼用戶可以知道服務器是請求處理成功、失敗或者是被轉發;這樣出現了錯誤也好定位。狀態碼是由3位數字加原因短語組成。3位數字中的第一位是用來指定狀態的類別。共有5種。
HTTP狀態碼一共有60多種,但是不用全部都記住,因為大部分在工作當中是不經常使用的。經常使用的大概就是16種,下面來詳細介紹。(其實最最常用的也就8種,下面有背景色的就是)
更加詳細的狀態碼請參考:http://tool.oschina.net/commons?type=5
1. 200:OK
這個沒有什么好說的,是代表請求被正常的處理成功了。
2. 204:No Content
請求處理成功,但是沒有數據實體返回,也不允許有實體返回。比如說HEAD請求,可能就會返回204 No Content,因為HEAD就是只獲取頭信息。這里簡單提一下205 Reset Content,和204 No Content的區別是不但沒有數據實體返回,而且還需要重置表單,方便用戶再次輸入。
3. 206:Partial Content
這是客戶端使用Content-Range指定了需要的實體數據的范圍,然后服務端處理請求成功之后返回用戶需要的這一部分數據而不是全部,執行的請求就是GET。返回碼就是206:Partial Content。
4. 301 : Moved Permanently
代表永久性定向。該狀態碼表示請求的資源已經被分配了新的URL,以后應該使用資源現在指定的URL。也就是說如果已經把資源對應的URL保存為書簽了,這是應該按照Location首部字段提示的URL重新保存。
5. 302:Found
代表臨時重定向。該狀態碼表示請求的資源已經被分配了新的URL,但是和301的區別是302代表的不是永久性的移動,只是臨時的。就是說這個URL還可能會發生改變。如果保存成書簽了也不會更新。
6. 303:See Other
和302的區別是303明確規定客戶端應當使用GET方法。
7. 304:Not Modified
該狀態碼表示客戶端發送附帶條件請求時,服務器端允許請求訪問資源,但是沒有滿足條件。304狀態碼返回時不包含任何數據實體。304雖然被划分在3XX中但是和重定向沒有關系。
8. 307:Temporary Redirect
臨時重定向,與302 Found相同,但是302會把POST改成GET,而307就不會。
9. 400:Bad Request
400表示請求報文中存在語法錯誤。需要修改后再次發送。
10. 401:Unauthorized
該狀態碼表示發送的請求需要有通過HTTP認證的認證信息。
11. 403:Forbidden
表明請求訪問的資源被拒絕了。沒有獲得服務器的訪問權限,IP被禁止等。
12. 404:Not Found
表明請求的資源在服務器上找不到。當然也可以在服務器拒絕請求且不想說明理由時使用。
13. 408:Request Timeout
表示客戶端請求超時,就是在客戶端和服務器建立連接后服務器在一定時間內沒有收到客戶端的請求。
14. 500:Internal Server Error
表明服務器端在執行請求時發生了錯誤,很有可能是服務端程序的Bug或者臨時故障。
15. 503:Service Unavailable
表明服務器暫時處於超負載或正在進行停機維護,現在無法處理請求。如果事先得知解除以上狀況需要的時間,最好寫入Retry-After字段再返回給客戶端。
16. 504:Getaway Timeout
網關超時,是代理服務器等待應用服務器響應時的超時,和408 Request Timeout的卻別就是504是服務器的原因而不是客戶端的原因
六、HTTP的首部字段
HTTP首部字段是構成HTTP報文最重要的元素之一。在客戶端與服務端之前進行信息傳遞的時候請求和響應都會使用首部字段,會傳遞一些重要的元信息。首部字段是以鍵值對的形式存在的。包含報文的主體大小、語言、認證信息等。HTTP首部字段包含4種類型:
- 通用首部字段(General Header Fields)
代表請求報文和響應報文都會使用的字段
- 請求首部字段(Request Header Fields)
是客戶端向服務端發送請求時使用的首部字段。包含請求的附加內容、客戶端信息、響應內容相關優先級等信息。
- 響應首部字段(Response Header Fields)
是服務端向客戶端返回響應時使用的首部字段,包含響應的附加內容,可能也會要求客戶端附加額外的內容信息。
- 實體首部字段(Entity Header Fields)
是針對請求報文和響應報文的實體部分使用的首部。包含資源內容更新時間等和實體有關的信息。
在HTTP/1.1種規定了47種首部字段(圖表參考《圖解HTTP》,感謝作者。)
1、通用首部字段
2、請求首部字段
3、響應首部字段
4、實體首部字段
5、其他首部字段
Cookie、Set-Cookie、Content-Disposition、Connection、Keep-Alive、Proxy-Authenticate、Proxy-Authorization、Trailer、TE、Transfer-Encoding、Upgrade etc...
這么多的首部字段,估計如果不是很了解會被嚇着,但是根本不用全部記住,其實字段的名字就說明了作用,看一眼就大概知道是干啥的了,只不過有些類似的字段要區分一下就好了。只要深刻理解了HTTP的設計思路就沒有大問題了,熟悉常見的就可以了。用到的時候想了解細節再去查。關於首部字段的細節請參考《圖解HTTP》或者《HTTP權威指南》的首部字段部分。夠再寫一篇長博客的了~以上就把HTTP協議的重點內容——報文格式、方法、狀態碼、首部字段介紹完了,可以說對HTTP協議有了一些了解。下面就工作中的常見問題(或者說面試中的)做一個總結。^_^
七、關於HTTP的常見問題及解答
1.GET和POST的區別
A. 從字面意思和HTTP的規范來看,GET用於獲取資源信息而POST是用來更新資源信息。
B. GET提交請求的數據實體會放在URL的后面,用?來分割,參數用&連接,舉個栗子:/index.html?name=wang&login=1
C. GET提交的數據長度是有限制的,因為URL長度有限制,具體的長度限制視瀏覽器而定。而POST沒有。
D. GET提交的數據不安全,因為參數都會暴露在URL上。
2.408 Request Timeout和504 Gateway Timeout的區別
408是說請求超時,就是建立連接之后再約定的時間內客戶端沒有發送請求到客戶端到服務端。本質上原因在於客戶端或者網絡擁塞。504是網關超時,是說代理服務器把客戶端請求轉發到應用服務器后再約定的時間內沒有收到應用服務器的響應。本質上原因在於服務端的響應過慢,也有可能是網絡問題。
3.Cookie和Session的區別和聯系
Cookie和Session都是為了保存客戶端和服務端之間的交互狀態,實現機制不同,各有優缺點。首先一個最大的區別就是Cookie是保存在客戶端而Session就保存在服務端的。Cookie是客戶端請求服務端時服務器會將一些信息以鍵值對的形式返回給客戶端,保存在瀏覽器中,交互的時候可以加上這些Cookie值。用Cookie就可以方便的做一些緩存。Cookie的缺點是大小和數量都有限制;Cookie是存在客戶端的可能被禁用、刪除、篡改,是不安全的;Cookie如果很大,每次要請求都要帶上,這樣就影響了傳輸效率。Session是基於Cookie來實現的,不同的是Session本身存在於服務端,但是每次傳輸的時候不會傳輸數據,只是把代表一個客戶端的唯一ID(通常是JSESSIONID)寫在客戶端的Cookie中,這樣每次傳輸這個ID就可以了。Session的優勢就是傳輸數據量小,比較安全。但是Session也有缺點,就是如果Session不做特殊的處理容易失效、過期、丟失或者Session過多導致服務器內存溢出,並且要實現一個穩定可用安全的分布式Session框架也是有一定復雜度的。在實際使用中就要結合Cookie和Session的優缺點針對不同的問題來設計解決方案。
4、Http與Https的區別
(1)HTTP 的URL 以http:// 開頭,而HTTPS 的URL 以https:// 開頭
(2)HTTP 是不安全的,而 HTTPS 是安全的
(3)HTTP 標准端口是80 ,而 HTTPS 的標准端口是443
(4)在OSI 網絡模型中,HTTP工作於應用層,而HTTPS 的安全傳輸機制工作在傳輸層
(5)HTTP 無法加密,而HTTPS 對傳輸的數據進行加密
(6)HTTP無需證書,而HTTPS 需要CA機構wosign的頒發的SSL證書
5、什么是Http無狀態協議?怎么解決Http無狀態協議?
無狀態協議對於事務處理沒有記憶能力。缺少狀態意味着如果后續處理需要前面的信息,也就是說,當客戶端一次HTTP請求完成以后,客戶端再發送一次HTTP請求,HTTP並不知道當前客戶端是一個”老用戶“。可以使用Cookie來解決無狀態的問題,Cookie就相當於一個通行證,第一次訪問的時候給客戶端發送一個Cookie,當客戶端再次來的時候,拿着Cookie(通行證),那么服務器就知道這個是”老用戶“。
6、URI和URL的區別
(1)URI(uniform resource identifier)統一資源標識符,用來唯一的標識一個資源。
- Web上可用的每種資源如HTML文檔、圖像、視頻片段、程序等都是用一個URI來定位的
- URI一般由三部組成:
①訪問資源的命名機制
②存放資源的主機名
③資源自身的名稱,由路徑表示,着重強調於資源。
(2)URL是uniform resource locator,統一資源定位器,它是一種具體的URI,即URL可以用來標識一個資源,而且還指明了如何locate這個資源。
- URL是Internet上用來描述信息資源的字符串,主要用在各種WWW客戶程序和服務器程序上,特別是著名的Mosaic。
- 采用URL可以用一種統一的格式來描述各種信息資源,包括文件、服務器的地址和目錄等
- URL一般由三部組成:
①協議(或稱為服務方式)
②存有該資源的主機IP地址(有時也包括端口號)
③主機資源的具體地址。如目錄和文件名等
(3)URN(uniform resource name)統一資源命名,是通過名字來標識資源,比如mailto:java-net@java.sun.com。
注意:URI是以一種抽象的,高層次概念定義統一資源標識,而URL和URN則是具體的資源標識的方式。URL和URN都是一種URI。籠統地說,每個 URL 都是 URI,但不一定每個 URI 都是 URL。這是因為 URI 還包括一個子類,即統一資源名稱 (URN),它命名資源但不指定如何定位資源。上面的 mailto、news 和 isbn URI 都是 URN 的示例。
7、HTTPS工作原理
具體的參考鏈接:http://blog.csdn.net/sean_cd/article/details/6966130
- 首先HTTP請求服務端生成證書,客戶端對證書的有效期、合法性、域名是否與請求的域名一致、證書的公鑰(RSA加密)等進行校驗;
- 客戶端如果校驗通過后,就根據證書的公鑰的有效, 生成隨機數,隨機數使用公鑰進行加密(RSA加密);
- 消息體產生的后,對它的摘要進行MD5(或者SHA1)算法加密,此時就得到了RSA簽名;
- 發送給服務端,此時只有服務端(RSA私鑰)能解密。
- 解密得到的隨機數,再用AES加密,作為密鑰(此時的密鑰只有客戶端和服務端知道)。
8、一次完整的HTTP請求所經歷的7個步驟
最具體的HTTP請求過程:http://blog.51cto.com/linux5588/1351007
HTTP通信機制是在一次完整的HTTP通信過程中,Web瀏覽器與Web服務器之間將完成下列7個步驟:
建立TCP連接->發送請求行->發送請求頭->(到達服務器)發送狀態行->發送響應頭->發送響應數據->斷TCP連接
(1)建立TCP連接
在HTTP工作開始之前,Web瀏覽器首先要通過網絡與Web服務器建立連接,該連接是通過TCP來完成的,該協議與IP協議共同構建 Internet,即著名的TCP/IP協議族,因此Internet又被稱作是TCP/IP網絡。HTTP是比TCP更高層次的應用層協議,根據規則, 只有低層協議建立之后才能進行更高層協議的連接,因此,首先要建立TCP連接,一般TCP連接的端口號是80。
(2)Web瀏覽器向Web服務器發送請求行
一旦建立了TCP連接,Web瀏覽器就會向Web服務器發送請求命令。例如:GET /sample/hello.jsp HTTP/1.1。
(3)Web瀏覽器發送請求頭
瀏覽器發送其請求命令之后,還要以頭信息的形式向Web服務器發送一些別的信息,之后瀏覽器發送了一空白行來通知服務器,它已經結束了該頭信息的發送。
(4)Web服務器應答
客戶機向服務器發出請求后,服務器會客戶機回送應答, HTTP/1.1 200 OK ,應答的第一部分是協議的版本號和應答狀態碼。
(5)Web服務器發送應答頭
正如客戶端會隨同請求發送關於自身的信息一樣,服務器也會隨同應答向用戶發送關於它自己的數據及被請求的文檔。
(6)Web服務器向瀏覽器發送數據
Web服務器向瀏覽器發送頭信息后,它會發送一個空白行來表示頭信息的發送到此為結束,接着,它就以Content-Type應答頭信息所描述的格式發送用戶所請求的實際數據。
(7)Web服務器關閉TCP連接
一般情況下,一旦Web服務器向瀏覽器發送了請求數據,它就要關閉TCP連接,然后如果瀏覽器或者服務器在其頭信息加入了下面代碼,TCP連接在發送后將仍然保持打開狀態,瀏覽器可以繼續通過相同的連接發送請求。保持連接節省了為每個請求建立新連接所需的時間,還節約了網絡帶寬。
Connection:keep-alive
9、HTTP優化方案
- TCP復用:TCP連接復用是將多個客戶端的HTTP請求復用到一個服務器端TCP連接上,而HTTP復用則是一個客戶端的多個HTTP請求通過一個TCP連接進行處理。前者是負載均衡設備的獨特功能;而后者是HTTP 1.1協議所支持的新功能,目前被大多數瀏覽器所支持。
- 內容緩存:將經常用到的內容進行緩存起來,那么客戶端就可以直接在內存中獲取相應的數據了。
- 壓縮:將文本數據進行壓縮,減少帶寬
- SSL加速(SSL Acceleration):使用SSL協議對HTTP協議進行加密,在通道內加密並加速
- TCP緩沖:通過采用TCP緩沖技術,可以提高服務器端響應時間和處理效率,減少由於通信鏈路問題給服務器造成的連接負擔。
參考資料: