當今web程序的開發技術真是百家爭鳴,ASP.NET, PHP, JSP,Perl, AJAX 等等。 不管Web技術在將來如何發展,理解Web程序之間通訊的基本協議至關重要, 由於它讓咱們理解了Web應用程序的內部工做. 本文將對HTTP協議進行詳細的實例講解,內容較多,但願你們耐心看。也但願對你們的開發工做或者測試工做有所幫助。使用Fiddler工具很是方便地捕獲HTTP Request和HTTP Response, 關於Fiddler工具的用法,請看我另外一篇博客[Fiddler 教程]html
閱讀目錄web
什麼是HTTP協議
協議是指計算機通訊網絡中兩臺計算機之間進行通訊所必須共同遵照的規定或規則,超文本傳輸協議(HTTP)是一種通訊協議,它容許將超文本標記語言(HTML)文檔從Web服務器傳送到客戶端的瀏覽器跨域
目前咱們使用的是HTTP/1.1 版本瀏覽器
Web服務器,瀏覽器,代理服務器
當咱們打開瀏覽器,在地址欄中輸入URL,而後咱們就看到了網頁。 原理是怎樣的呢?緩存
實際上咱們輸入URL後,咱們的瀏覽器給Web服務器發送了一個Request, Web服務器接到Request後進行處理,生成相應的Response,而後發送給瀏覽器, 瀏覽器解析Response中的HTML,這樣咱們就看到了網頁,過程以下圖所示安全
咱們的Request 有多是通過了代理服務器,最後纔到達Web服務器的。服務器
過程以下圖所示cookie
代理服務器就是網絡信息的中轉站,有什麼功能呢?網絡
1. 提升訪問速度, 大多數的代理服務器都有緩存功能。app
2. 突破限制, 也就是FQ了
3. 隱藏身份。
URL詳解
URL(Uniform Resource Locator) 地址用於描述一個網絡上的資源, 基本格式以下
schema://host[:port#]/path/.../[?query-string][#anchor]
scheme 指定低層使用的協議(例如:http, https, ftp)
host HTTP服務器的IP地址或者域名
port# HTTP服務器的默認端口是80,這種狀況下端口號能夠省略。若是使用了別的端口,必須指明,例如 http://www.cnblogs.com:8080/
path 訪問資源的路徑
query-string 發送給http服務器的數據
anchor- 錨
URL 的一個例子
http://www.mywebsite.com/sj/test/test.aspx?name=sviergn&x=true#stuff
Schema: http
host: www.mywebsite.com
path: /sj/test/test.aspx
Query String: name=sviergn&x=true
Anchor: stuff
HTTP協議是無狀態的
http協議是無狀態的,同一個客戶端的此次請求和上次請求是沒有對應關係,對http服務器來講,它並不知道這兩個請求來自同一個客戶端。 爲了解決這個問題, Web程序引入了Cookie機制來維護狀態.
HTTP消息的結構
先看Request 消息的結構, Request 消息分爲3部分,第一部分叫Request line, 第二部分叫Request header, 第三部分是body. header和body之間有個空行, 結構以下圖
第一行中的Method表示請求方法,好比"POST","GET", Path-to-resoure表示請求的資源, Http/version-number 表示HTTP協議的版本號
當使用的是"GET" 方法的時候, body是爲空的
好比咱們打開博客園首頁的request 以下
GET http://www.cnblogs.com/ HTTP/1.1
Host: www.cnblogs.com
抽象的東西,難以理解,老感受是虛的, 所謂眼見爲實, 實際見到的東西,咱們才能理解和記憶。 咱們今天用Fiddler,實際的看看Request和Response.
下面咱們打開Fiddler 捕捉一個博客園登陸的Request 而後分析下它的結構, 在Inspectors tab下以Raw的方式能夠看到完整的Request的消息, 以下圖
咱們再看Response消息的結構, 和Request消息的結構基本同樣。 一樣也分爲三部分,第一部分叫Response line, 第二部分叫Response header,第三部分是body. header和body之間也有個空行, 結構以下圖
HTTP/version-number表示HTTP協議的版本號, status-code 和message 請看下節[狀態代碼]的詳細解釋.
咱們用Fiddler 捕捉一個博客園首頁的Response而後分析下它的結構, 在Inspectors tab下以Raw的方式能夠看到完整的Response的消息, 以下圖
Get和Post方法的區別
Http協議定義了不少與服務器交互的方法,最基本的有4種,分別是GET,POST,PUT,DELETE. 一個URL地址用於描述一個網絡上的資源,而HTTP中的GET, POST, PUT, DELETE就對應着對這個資源的查,改,增,刪4個操做。 咱們最多見的就是GET和POST了。GET通常用於獲取/查詢資源信息,而POST通常用於更新資源信息.
咱們看看GET和POST的區別
1. GET提交的數據會放在URL以後,以?分割URL和傳輸數據,參數之間以&相連,如EditPosts.aspx?name=test1&id=123456. POST方法是把提交的數據放在HTTP包的Body中.
2. GET提交的數據大小有限制(由於瀏覽器對URL的長度有限制),而POST方法提交的數據沒有限制.
3. GET方式須要使用Request.QueryString來取得變量的值,而POST方式經過Request.Form來獲取變量的值。
4. GET方式提交數據,會帶來安全問題,好比一個登陸頁面,經過GET方式提交數據時,用戶名和密碼將出如今URL上,若是頁面能夠被緩存或者其餘人能夠訪問這臺機器,就能夠從歷史記錄得到該用戶的帳號和密碼.
狀態碼
Response 消息中的第一行叫作狀態行,由HTTP協議版本號, 狀態碼, 狀態消息 三部分組成。
狀態碼用來告訴HTTP客戶端,HTTP服務器是否產生了預期的Response.
HTTP/1.1中定義了5類狀態碼, 狀態碼由三位數字組成,第一個數字定義了響應的類別
1XX 提示信息 - 表示請求已被成功接收,繼續處理
2XX 成功 - 表示請求已被成功接收,理解,接受
3XX 重定向 - 要完成請求必須進行更進一步的處理
4XX 客戶端錯誤 - 請求有語法錯誤或請求沒法實現
5XX 服務器端錯誤 - 服務器未能實現合法的請求
看看一些常見的狀態碼
200 OK
最多見的就是成功響應狀態碼200了, 這代表該請求被成功地完成,所請求的資源發送回客戶端
以下圖, 打開博客園首頁
302 Found
重定向,新的URL會在response 中的Location中返回,瀏覽器將會自動使用新的URL發出新的Request
例如在IE中輸入, http://www.google.com. HTTP服務器會返回302, IE取到Response中Location header的新URL, 又從新發送了一個Request.
304 Not Modified
表明上次的文檔已經被緩存了, 還能夠繼續使用,
例如打開博客園首頁, 發現不少Response 的status code 都是304
提示: 若是你不想使用本地緩存能夠用Ctrl+F5 強制刷新頁面
400 Bad Request 客戶端請求與語法錯誤,不能被服務器所理解
403 Forbidden 服務器收到請求,可是拒絕提供服務
404 Not Found
請求資源不存在(輸錯了URL)
好比在IE中輸入一個錯誤的URL, http://www.cnblogs.com/tesdf.aspx
500 Internal Server Error 服務器發生了不可預期的錯誤
503 Server Unavailable 服務器當前不能處理客戶端的請求,一段時間後可能恢復正常
使用Fiddler 能很方便的查看Reques header, 點擊Inspectors tab ->Request tab-> headers 以下圖所示.
header 有不少,比較難以記憶,咱們也按照Fiddler那樣把header 進行分類,這樣比較清晰也容易記憶。
Cache 頭域
If-Modified-Since
做用: 把瀏覽器端緩存頁面的最後修改時間發送到服務器去,服務器會把這個時間與服務器上實際文件的最後修改時間進行對比。若是時間一致,那麼返回304,客戶端就直接使用本地緩存文件。若是時間不一致,就會返回200和新的文件內容。客戶端接到以後,會丟棄舊文件,把新文件緩存起來,並顯示在瀏覽器中.
例如:If-Modified-Since: Thu, 09 Feb 2012 09:07:57 GMT
實例以下圖
If-None-Match
做用: If-None-Match和ETag一塊兒工做,工做原理是在HTTP Response中添加ETag信息。 當用戶再次請求該資源時,將在HTTP Request 中加入If-None-Match信息(ETag的值)。若是服務器驗證資源的ETag沒有改變(該資源沒有更新),將返回一個304狀態告訴客戶端使用本地緩存文件。不然將返回200狀態和新的資源和Etag. 使用這樣的機制將提升網站的性能
例如: If-None-Match: "03f2b33c0bfcc1:0"
實例以下圖
Pragma
做用: 防止頁面被緩存, 在HTTP/1.1版本中,它和Cache-Control:no-cache做用如出一轍
Pargma只有一個用法, 例如: Pragma: no-cache
注意: 在HTTP/1.0版本中,只實現了Pragema:no-cache, 沒有實現Cache-Control
Cache-Control
做用: 這個是很是重要的規則。 這個用來指定Response-Request遵循的緩存機制。各個指令含義以下
Cache-Control:Public 能夠被任何緩存所緩存()
Cache-Control:Private 內容只緩存到私有緩存中
Cache-Control:no-cache 全部內容都不會被緩存
還有其餘的一些用法, 我沒搞懂其中的意思, 請你們參考其餘的資料
Client 頭域
Accept
做用: 瀏覽器端能夠接受的媒體類型,
例如: Accept: text/html 表明瀏覽器能夠接受服務器回發的類型爲 text/html 也就是咱們常說的html文檔,
若是服務器沒法返回text/html類型的數據,服務器應該返回一個406錯誤(non acceptable)
通配符 * 表明任意類型
例如 Accept: */* 表明瀏覽器能夠處理全部類型,(通常瀏覽器發給服務器都是發這個)
Accept-Encoding:
做用: 瀏覽器申明本身接收的編碼方法,一般指定壓縮方法,是否支持壓縮,支持什麼壓縮方法(gzip,deflate),(注意:這不是隻字符編碼);
例如: Accept-Encoding: gzip, deflate
Accept-Language
做用: 瀏覽器申明本身接收的語言。
語言跟字符集的區別:中文是語言,中文有多種字符集,好比big5,gb2312,gbk等等;
例如: Accept-Language: en-us
User-Agent
做用:告訴HTTP服務器, 客戶端使用的操做系統和瀏覽器的名稱和版本.
咱們上網登錄論壇的時候,每每會看到一些歡迎信息,其中列出了你的操做系統的名稱和版本,你所使用的瀏覽器的名稱和版本,這每每讓不少人感到很神奇,實際上,服務器應用程序就是從User-Agent這個請求報頭域中獲取到這些信息User-Agent請求報頭域容許客戶端將它的操做系統、瀏覽器和其它屬性告訴服務器。
例如: User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; CIBA; .NET CLR 2.0.50727; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; .NET4.0C; InfoPath.2; .NET4.0E)
Accept-Charset
做用:瀏覽器申明本身接收的字符集,這就是本文前面介紹的各類字符集和字符編碼,如gb2312,utf-8(一般咱們說Charset包括了相應的字符編碼方案);
例如:
Cookie/Login 頭域
Cookie:
做用: 最重要的header, 將cookie的值發送給HTTP 服務器
Entity頭域
Content-Length
做用:發送給HTTP服務器數據的長度。
例如: Content-Length: 38
Content-Type
做用:
例如:Content-Type: application/x-www-form-urlencoded
Miscellaneous 頭域
Referer:
做用: 提供了Request的上下文信息的服務器,告訴服務器我是從哪一個連接過來的,好比從我主頁上連接到一個朋友那裏,他的服務器就可以從HTTP Referer中統計出天天有多少用戶點擊我主頁上的連接訪問他的網站。
例如: Referer:http://translate.google.cn/?hl=zh-cn&tab=wT
Transport 頭域
Connection
例如: Connection: keep-alive 當一個網頁打開完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP鏈接不會關閉,若是客戶端再次訪問這個服務器上的網頁,會繼續使用這一條已經創建的鏈接
例如: Connection: close 表明一個Request完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP鏈接會關閉, 當客戶端再次發送Request,須要從新創建TCP鏈接。
Host(發送請求時,該報頭域是必需的)
做用: 請求報頭域主要用於指定被請求資源的Internet主機和端口號,它一般從HTTP URL中提取出來的
例如: 咱們在瀏覽器中輸入:http://www.guet.edu.cn/index.html
瀏覽器發送的請求消息中,就會包含Host請求報頭域,以下:
Host:http://www.guet.edu.cn
此處使用缺省端口號80,若指定了端口號,則變成:Host:指定端口號
HTTP Response header
一樣使用Fiddler 查看Response header, 點擊Inspectors tab ->Response tab-> headers 以下圖所示
咱們也按照Fiddler那樣把header 進行分類,這樣比較清晰也容易記憶。
Cache頭域
Date
做用: 生成消息的具體時間和日期
例如: Date: Sat, 11 Feb 2012 11:35:14 GMT
Expires
做用: 瀏覽器會在指定過時時間內使用本地緩存
例如: Expires: Tue, 08 Feb 2022 11:35:14 GMT
Vary
做用:
例如: Vary: Accept-Encoding
Cookie/Login 頭域
P3P
做用: 用於跨域設置Cookie, 這樣能夠解決iframe跨域訪問cookie的問題
例如: P3P: CP=CURa ADMa DEVa PSAo PSDo OUR BUS UNI PUR INT DEM STA PRE COM NAV OTC NOI DSP COR
Set-Cookie
做用: 很是重要的header, 用於把cookie 發送到客戶端瀏覽器, 每個寫入cookie都會生成一個Set-Cookie.
例如: Set-Cookie: sc=4c31523a; path=/; domain=.acookie.taobao.com
Entity頭域
ETag
做用: 和If-None-Match 配合使用。 (實例請看上節中If-None-Match的實例)
例如: ETag: "03f2b33c0bfcc1:0"
Last-Modified:
做用: 用於指示資源的最後修改日期和時間。(實例請看上節的If-Modified-Since的實例)
例如: Last-Modified: Wed, 21 Dec 2011 09:09:10 GMT
Content-Type
做用:WEB服務器告訴瀏覽器本身響應的對象的類型和字符集,
例如:
Content-Type: text/html; charset=utf-8
Content-Type:text/html;charset=GB2312
Content-Type: image/jpeg
Content-Length
指明實體正文的長度,以字節方式存儲的十進制數字來表示。在數據下行的過程當中,Content-Length的方式要預先在服務器中緩存全部數據,而後全部數據再一古腦兒地發給客戶端。
例如: Content-Length: 19847
Content-Encoding
WEB服務器代表本身使用了什麼壓縮方法(gzip,deflate)壓縮響應中的對象。
例如:Content-Encoding:gzip
Content-Language
做用: WEB服務器告訴瀏覽器本身響應的對象的語言者
例如: Content-Language:da
Miscellaneous 頭域
Server:
做用:指明HTTP服務器的軟件信息
例如:Server: Microsoft-IIS/7.5
X-AspNet-Version:
做用:若是網站是用ASP.NET開發的,這個header用來表示ASP.NET的版本
例如: X-AspNet-Version: 4.0.30319
X-Powered-By:
做用:表示網站是用什麼技術開發的
例如: X-Powered-By: ASP.NET
Transport頭域
Connection
例如: Connection: keep-alive 當一個網頁打開完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP鏈接不會關閉,若是客戶端再次訪問這個服務器上的網頁,會繼續使用這一條已經創建的鏈接
例如: Connection: close 表明一個Request完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP鏈接會關閉, 當客戶端再次發送Request,須要從新創建TCP鏈接。
Location頭域
Location
做用: 用於重定向一個新的位置, 包含新的URL地址
實例請看304狀態實例
HTTP協議是無狀態的和Connection: keep-alive的區別
無狀態是指協議對於事務處理沒有記憶能力,服務器不知道客戶端是什麼狀態。從另外一方面講,打開一個服務器上的網頁和你以前打開這個服務器上的網頁之間沒有任何聯繫
HTTP是一個無狀態的面向鏈接的協議,無狀態不表明HTTP不能保持TCP鏈接,更不能表明HTTP使用的是UDP協議(無鏈接)
從HTTP/1.1起,默認都開啓了Keep-Alive,保持鏈接特性,簡單地說,當一個網頁打開完成後,客戶端和服務器之間用於傳輸HTTP數據的TCP鏈接不會關閉,若是客戶端再次訪問這個服務器上的網頁,會繼續使用這一條已經創建的鏈接
Keep-Alive不會永久保持鏈接,它有一個保持時間,能夠在不一樣的服務器軟件(如Apache)中設定這個時間
若是您以爲本篇博客對你有所收穫請點擊右下角的 [推薦]
若是您想轉載本博客,請註明出處
若是你對本文有意見或者建議,歡迎留言
感謝您的閱讀,請關注個人後續博客