對於靜態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頁面,即使這個頁面的內容沒有任何動態代碼。
比如:
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title></title>
- </head>
- <body>
- <form id="form1">
- <div>
- 不修改
- </div>
- </form>
- </body>
- </html>
-
每次請求也總是得到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代碼實現如下:
- <%@ Page Title="首頁" Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
- Inherits="WebApplication1._Default" %>
- <%
- Response.Write("If - Modified - Since:" + Request.Headers["If-Modified-Since"] + "<br/>"); //列印讀取的要求標頭中If-Modified-Since的值
- Response.Write("Now:" + DateTime.Now.ToString() + "<br/>");//列印目前時間
- DateTime If_Modified_Since = new DateTime();
- if (Request.Headers["If-Modified-Since"] == null || Request.Headers["If-Modified-Since"] == "")
- {
- If_Modified_Since = new DateTime(1900, 1, 1);//如果讀取的要求標頭中If-Modified-Since沒有值,就給它一個預設值為19000101
- }
- else
- {
- If_Modified_Since = DateTime.Parse(Request.Headers["If-Modified-Since"]);
- }
- if (If_Modified_Since.AddSeconds(10) > DateTime.Now)//如果緩衝最後的修改時間和目前時間相差10s內
- {
- Response.StatusCode = 304;//返回304代碼,使其讀取緩衝
- Response.End();
- }
- else//否則
- {
- //顯示內容
- Response.AddHeader("last-modified", DateTime.Now.ToString());
- Response.Write("Content Changed;" + DateTime.Now.ToString()+"<br>");
- }
- %>
PHP代碼如下:
- <?php
- date_default_timezone_set('PRC'); //中華人民共和國時間
- $arr=getallheaders();
- $If_Modified_Since = new DateTime();
- if(isset($arr["If-Modified-Since"])==false)
- {
- $If_Modified_Since = new DateTime("1900-1-1");//如果讀取的要求標頭中If-Modified-Since沒有值,就給它一個預設值為19000101
- }
- else
- { //echo "##<br>";
- //echo "If-Modified-Since:".$arr["If-Modified-Since"]."<br>";
- //echo "##<br>";
- $If_Modified_Since = new DateTime($arr["If-Modified-Since"]);
- }
- $now=new DateTime();
- echo "##<br>";
- echo $now->format('Y-m-d H:i:s')."---".$If_Modified_Since->format('Y-m-d H:i:s')."<br>";
- echo "##<br>";
- $diff=strtotime($now->format('Y-m-d H:i:s'))-strtotime($If_Modified_Since->format('Y-m-d H:i:s'));
- echo "diff:"."$diff<br>";
- if ($diff <10)//如果緩衝最後的修改時間和目前時間相差10s內
- {
- header('Etag:',true,304);//返回304代碼,使其讀取緩衝
- exit();
- }
- else//否則
- {
- $now=new DateTime();
- //顯示內容
- header ("last-modified:".$now->format('Y-m-d H:i:s'));
- print("Content Changed:" .$now->format('Y-m-d H:i:s')."<br>");
- }
- ?>
-
以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