1. 程式人生 > >理解HTTP協議(轉載)

理解HTTP協議(轉載)

網站 解決 part 轉發 工作 包含 reset 多次 per

  HTTP(HyperText Transfer Protocol)協議是基於TCP的應用層協議,它不關心數據傳輸的細節,主要是用來規定客戶端和服務端的數據傳輸格式,最初是用來向客戶端傳輸HTML頁面的內容。默認端口是80。

  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://www.ruanyifeng.com/blog/2016/08/http.html

  下面介紹沒有特殊說明默認HTTP/1.1版本

二、HTTP協議的特點

  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種,下面有背景色的就是)

  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://tool.oschina.net/commons?type=5

六、HTTP的首部字段

  HTTP首部字段是構成HTTP報文最重要的元素之一。在客戶端與服務端之前進行信息傳遞的時候請求和響應都會使用首部字段,會傳遞一些重要的元信息。首部字段是以鍵值對的形式存在的。包含報文的主體大小、語言、認證信息等。HTTP首部字段包含4種類型:

  通用首部字段(General Header Fields)

  代表請求報文和響應報文都會使用的字段

  請求首部字段(Request Header Fields)

  是客戶端向服務端發送請求時使用的首部字段。包含請求的附加內容、客戶端信息、響應內容相關優先級等信息。

  響應首部字段(Response Header Fields)

  是服務端向客戶端返回響應時使用的首部字段,包含響應的附加內容,可能也會要求客戶端附加額外的內容信息。

  實體首部字段(Entity Header Fields)

  是針對請求報文和響應報文的實體部分使用的首部。包含資源內容更新時間等和實體有關的信息。

  在HTTP/1.1種規定了47種首部字段(圖表參考《圖解HTTP》,感謝作者。)

  通用首部字段

   技術分享圖片

  請求首部字段

   技術分享圖片

  響應首部字段

   技術分享圖片

  實體首部字段

   技術分享圖片

  其他首部字段

    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的優缺點針對不同的問題來設計解決方案。

理解HTTP協議(轉載)