HTTP 緩衝概念和強迫瀏覽器使用緩衝的樣本

來源:互聯網
上載者:User

對於靜態html頁面,瀏覽器首次訪問後會把該網頁放入存入緩衝。

再次訪問該頁面的時候,要求標頭會附上:

If-Modified-Since: Mon, 17 Sep 2012 08:52:31 GMT之樣的資料。

發送給伺服器,伺服器收到後發現這個日期之後沒更改,就發送304響應給用戶端。用戶端就乖乖的顯示它自己的緩衝了。

如果你按住CTRL+F5,則表示強制重新整理,要求標頭中不包含If-Modified-Since。因此伺服器收到後直接發送200響應。

對於用ASP.NET所用到的緩衝,也是有同樣的效果。比如下面的這個頁面代碼:

<%@ OutputCache Duration="600" VaryByParam="None"%>

default:<%Response.Write(DateTime.Now.ToString("yyyyMMdd")); %>

此處如果設定Location="ServerAndClient",那麼第二次訪問是304響應。訪問該頁面的時候和訪問html相同,第二次訪問會有304響應。當然,如果頁面更新後,就又會得到200響應。那是因為要求標頭中會有If-Modified-Since:Tue, 18 Sep 2012 12:32:14 GMT這樣的資料。註:在Chrome嘗試,會有304響應。但是在firefox中嘗試,要求標頭沒有If-Modified-Since資訊,因此沒有304,每次都是200響應。原因不明。)

此處如果設定Location="Server",那麼每次都是200響應。這個緩衝在Server記憶體裡,因此雖然每次都是200,但是節省了產生頁面的開銷。
Location="Server"的時候,回應標頭變成Cache-Control:no-cache,其實即使回應標頭Cache-Control標記為no-cache,本地還是會有緩衝的,只是在沒有首次驗證內容是否為最新的情況下,不會把cache內容發送給用戶端,no-cache更好的名稱是“沒有驗證是否最新就不作為輸出的cache”註:出自《HTTP The Definitive Guide》by David Gourley and Brian Totty)

此處如果設定Location="Client",那麼每次都是200響應。這個就是疑問的地方,雖然用戶端有緩衝了,而且要求標頭也會有If-Modified-Since,伺服器資料也未改變,但還是返回了200。此處推測對於動態網頁面,如果沒有特殊的處理,總是返回200狀態。

比如下面的頁面,假設是一個php頁面,或者aspx頁面,即使這個頁面的內容沒有任何動態代碼。

比如: 

 
  1. <html xmlns="http://www.w3.org/1999/xhtml"> 
  2. <head> 
  3.     <title></title> 
  4. </head> 
  5. <body> 
  6.     <form id="form1"> 
  7.     <div> 
  8.     不修改  
  9.     </div> 
  10.     </form> 
  11. </body> 
  12. </html> 
  13.  

 每次請求也總是得到200響應,從不用緩衝。

下面示範一下,伺服器端通過發送304狀態,欺騙用戶端調用自己的緩衝,以達到緩解網路壓力的目的。

先說明幾點測試下來的規則:

response回應標頭last-modified,緩衝到用戶端後,即用戶端重新整理的時候,這個值會成為用戶端的request要求標頭的值。

比如 Response.AddHeader("last-modified", new DateTime(2000,1,1),那麼當重新整理或者重新提交這個頁面的時候,Request.Headers["If-Modified-Since"]的值就是2001-01-01。因此,If-Modified-Since可以理解為緩衝最後的更新時間。

假設實現下面的一個功能,如果用戶端請求過某一個頁面後,那麼10秒之內,用戶端再次請求,伺服器端都發送304狀態代碼,要求其讀取緩衝。用戶端如果CTRL+F5沒辦法讀緩衝的)

ASPX代碼實現如下: 

 
  1. <%@ Page Title="首頁" Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" 
  2.     Inherits="WebApplication1._Default" %>  
  3. <%  
  4.     Response.Write("If - Modified - Since:" + Request.Headers["If-Modified-Since"] + "<br/>"); //列印讀取的要求標頭中If-Modified-Since的值  
  5.     Response.Write("Now:" + DateTime.Now.ToString() + "<br/>");//列印目前時間  
  6.     DateTime If_Modified_Since = new DateTime();  
  7.     if (Request.Headers["If-Modified-Since"] == null || Request.Headers["If-Modified-Since"] == "")  
  8.     {  
  9.         If_Modified_Since = new DateTime(1900, 1, 1);//如果讀取的要求標頭中If-Modified-Since沒有值,就給它一個預設值為19000101  
  10.     }  
  11.     else 
  12.     {  
  13.         If_Modified_Since = DateTime.Parse(Request.Headers["If-Modified-Since"]);  
  14.     }  
  15.     if (If_Modified_Since.AddSeconds(10) > DateTime.Now)//如果緩衝最後的修改時間和目前時間相差10s內  
  16.     {  
  17.         Response.StatusCode = 304;//返回304代碼,使其讀取緩衝  
  18.         Response.End();  
  19.     }  
  20.     else//否則  
  21.     {  
  22.         //顯示內容  
  23.         Response.AddHeader("last-modified", DateTime.Now.ToString());  
  24.         Response.Write("Content Changed;" + DateTime.Now.ToString()+"<br>");  
  25.     }  
  26. %>  

 PHP代碼如下: 

 
  1. <?php  
  2. date_default_timezone_set('PRC'); //中華人民共和國時間   
  3.     $arr=getallheaders();  
  4.     $If_Modified_Since = new DateTime();  
  5.     if(isset($arr["If-Modified-Since"])==false)  
  6.     {  
  7.         $If_Modified_Since = new DateTime("1900-1-1");//如果讀取的要求標頭中If-Modified-Since沒有值,就給它一個預設值為19000101  
  8.     }  
  9.     else 
  10.     { //echo "##<br>";  
  11. //echo "If-Modified-Since:".$arr["If-Modified-Since"]."<br>";  
  12. //echo "##<br>";  
  13.         $If_Modified_Since = new DateTime($arr["If-Modified-Since"]);  
  14.     }  
  15. $now=new DateTime();  
  16. echo "##<br>";  
  17. echo $now->format('Y-m-d H:i:s')."---".$If_Modified_Since->format('Y-m-d H:i:s')."<br>";  
  18. echo "##<br>";  
  19. $diff=strtotime($now->format('Y-m-d H:i:s'))-strtotime($If_Modified_Since->format('Y-m-d H:i:s'));  
  20. echo "diff:"."$diff<br>";  
  21. if ($diff <10)//如果緩衝最後的修改時間和目前時間相差10s內  
  22.     {  
  23.        header('Etag:',true,304);//返回304代碼,使其讀取緩衝  
  24.         exit();  
  25.     }  
  26.     else//否則  
  27.     {  
  28. $now=new DateTime();  
  29.         //顯示內容  
  30. header ("last-modified:".$now->format('Y-m-d H:i:s'));   
  31.         print("Content Changed:" .$now->format('Y-m-d H:i:s')."<br>");  
  32.     }  
  33. ?>  
  34.  

 以PHP頁面為例:

首次訪問的時候,得到回應標頭為200,要求標頭中並沒有If_Modified_Since

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="clipboard" border="0" alt="clipboard" height="406" src="http://www.bkjia.com/uploads/allimg/131228/1245014415-0.png" />

10s內再次訪問:

650) this.width=650;" style="border-bottom: 0px; border-left: 0px; border-top: 0px; border-right: 0px" title="clipboard[1]" border="0" alt="clipboard[1]" height="463" src="http://www.bkjia.com/uploads/allimg/131228/1245015X3-1.png" />

發送的If_Modified_Since頭的值為2012-09-18 16:16:30。距離伺服器目前時間在10s內,因此伺服器發送了304,迫使瀏覽器調用緩衝。

本文出自 “一隻部落格” 部落格,請務必保留此出處http://cnn237111.blog.51cto.com/2359144/997633

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.