rainbowzc

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: :: :: 管理 ::
一.前言

注重上网隐私和安全的人在每次上网后都会清除上网痕迹——“删除cookies”、“删除掉上网的临时缓存文件”以及“删除上网历史”。你觉得这样,所有的一切都会被擦除掉了。但是如果有人告诉你:这是不够的,系统中还有一些地方保存了你的上网信息,你是不是感到很恐慌?——这就是系统中的index.dat文件。

Windows系统中会存在三个index.dat文件。它们分别用来保存IE上网的cookies、临时文件和上网历史的索引信息(现在知道为什么这些文件名字是index.dat了吧J)。根据Windows系统版本不同,这些文件在系统中的位置也是不尽相同的。

在Windows 95/98/Me/ NT中,index.dat一般会存放在下面的位置中:
复制  保存
C:\Windows\Cookies\index.dat
C:\Windows\History\History.IE5\index.dat
C:\Windows\Temporary Internet Files\Content.IE5\index.dat

而在Window2000/XP系统中,index.dat一般会存在于下面的位置中:
复制  保存
C:\Documents and Settings\<username>\Cookies\index.dat
C:\Documents and Settings\<username>\Local Settings\History\History.IE5\index.dat
C:\Documents and Settings\<username>\Local Settings

\Temporary Internet Files\Content.IE5\index.dat

这些index.dat文件是系统、隐藏的文件,它们不随IE浏览器中的cookies值、临时文件和历史记录的清除而删除——这就是它的可怕之处。下面来详细描述index.dat文件的结构。


二.Index.dat文件结构

Index.dat文件分为两部分,头部分和条目(Entry)部分。

所谓头部分,顾名思义就是文件开始部分。它记录着这个文件的总的信息,如文件文件格式版本、大小、子文件夹等等。每个index.dat文件仅有一个头部分。

其余的部分都是条目部分。Index.dat中的各种类型的条目数据结构不同,不过每个条目的前8个字节结构相同,系统就是用这两个DWORD字段来区分条目类型的。

下面我们来具体分析一下各个部分:

1.头部分

index.dat的头部大小是固定的,为16K。其开始592个字节(0x250)为小(SMALL)的头部分。紧接着的空间是3948个DWORD,它用来作为分配MAP。数据结构如下:
复制  保存
struct CacheDir
{
   DWORD nFileCount;
   CHAR sDirName[8];
};
 
typedef struct _MEMMAP_HEADER_SMALL 
{
TCHAR    FileSignature[28]; //”Client UrlCache MMF Ver 5.2”
    DWORD    FileSize;         //index.dat文件的大小
    DWORD    dwHashTableOffset;  //第一个哈希表的偏移
    DWORD    NumUrlInternalEntries;
    DWORD    NumUrlEntriesAlloced;
  // DWORD    dwGarbage; // 无效数据,只在/Zp8编译使用
    LONGLONG CacheLimit;
    LONGLONG CacheSize;
    LONGLONG ExemptUsage;
    DWORD    nDirCount;     //子目录个数
    CacheDir DirArray[32];     //子目录名称
    DWORD    dwHeaderData[33];
} MEMMAP_HEADER_SMALL;
 
typedef struct _MEMMAP_HEADER : _MEMMAP_HEADER_SMALL 
{
    DWORD AllocationBitMap[3948];
} MEMMAP_HEADER, *LPMEMMAP_HEADER;


2.各种条目结构

上文说过每个条目都是以同样结构的2个DWORD开始的,这个结构如下:
复制  保存
typedef struct FILEMAP_ENTRY
{
    DWORD dwSig;  //条目标识
    DWORD nBlocks; //条目占用多少个快(128字节)
} *LPFILEMAP_ENTRY;

dwSig用来标识各种类型的标识。
表示字 说明
SIG_FREE 0xbadf00d 本条目空闲,只有此类条目没有nBlocks成员。
SIG_ALLOC 0xdeadbeef 已分配
SIG_URL ' LRU' URL
SIG_REDIR 'RDER' REDIR
SIG_LEAK 'KAEL' LEAK
SIG_GLIST 'GLST' GLIST
SIG_HASH 'HSAH' 哈希表

关于各种条目的结构我们下面会详细说明。

nBlocks用来描述此条目所占用的块数。注意index.dat中的块大小为128字节。


2.1哈希表条目

现在开始说明各种类型的条目。为什么先要说哈希表呢?这是因为index.dat使用一个哈希表链来作为目录,从而能够快速找到指定名称的条目。

Index.dat文件中每个哈希表大小都不能超过一个内存分页,即不能超过4K大小。每个哈希表部分是由下面的结构开始的,同时系统也是利用了这个结构,将index.dat中所有的哈希表部分链接起来的。
复制  保存
struct HASH_FILEMAP_ENTRY : FILEMAP_ENTRY
{
    DWORD dwNext; // 下一个哈希表偏移(0表示为最后一个)
                  //偏移以index.dat文件第0字节为基地址。
    DWORD nBlock; // 本哈希表的序列号。从0,1,2…….
};

紧接着这个结构就是一个哈希表,每个哈希表的关键是哈希函数,下面是这个哈希表的哈希函数:
复制  保存
PRIVATE DWORD HashKey (LPCSTR lpsz)
{
    union
    {
        DWORD dw;
        BYTE c[4];
    }
    Hash, Hash2;
        
    const static BYTE bTranslate[256] =
    {
        1, 14,110, 25, 97,174,132,119,138,170,125,118, 27,233,140, 51,
        87,197,177,107,234,169, 56, 68, 30,  7,173, 73,188, 40, 36, 65,
        49,213,104,190, 57,211,148,223, 48,115, 15,  2, 67,186,210, 28,
        12,181,103, 70, 22, 58, 75, 78,183,167,238,157,124,147,172,144,
        176,161,141, 86, 60, 66,128, 83,156,241, 79, 46,168,198, 41,254,
        178, 85,253,237,250,154,133, 88, 35,206, 95,116,252,192, 54,221,
        102,218,255,240, 82,106,158,201, 61,  3, 89,  9, 42,155,159, 93,
        166, 80, 50, 34,175,195,100, 99, 26,150, 16,145,  4, 33,  8,189,
        121, 64, 77, 72,208,245,130,122,143, 55,105,134, 29,164,185,194,
        193,239,101,242,  5,171,126, 11, 74, 59,137,228,108,191,232,139,
        6, 24, 81, 20,127, 17, 91, 92,251,151,225,207, 21, 98,113,112,
        84,226, 18,214,199,187, 13, 32, 94,220,224,212,247,204,196, 43,
        249,236, 45,244,111,182,153,136,129, 90,217,202, 19,165,231, 71,
        230,142, 96,227, 62,179,246,114,162, 53,160,215,205,180, 47,109,
        44, 38, 31,149,135,  0,216, 52, 63, 23, 37, 69, 39,117,146,184,
        163,200,222,235,248,243,219, 10,152,131,123,229,203, 76,120,209
    };
 
    // Seed the hash values based on the first character.
    Hash.c[0] = bTranslate[ *lpsz];
    Hash.c[1] = bTranslate[(*lpsz+1) & 255];
    Hash.c[2] = bTranslate[(*lpsz+2) & 255];
    Hash.c[3] = bTranslate[(*lpsz+3) & 255];
 
    while (*++lpsz)
    {
        // Allow URLs differing only by trailing slash to collide.
        if (lpsz[0] == '/' && lpsz[1] == 0)
            break;
 
        Hash2.c[0] = Hash.c[0] ^ *lpsz;
        Hash2.c[1] = Hash.c[1] ^ *lpsz;
        Hash2.c[2] = Hash.c[2] ^ *lpsz;
        Hash2.c[3] = Hash.c[3] ^ *lpsz;
            
        Hash.c[0] = bTranslate[Hash2.c[0]];
        Hash.c[1] = bTranslate[Hash2.c[1]];
        Hash.c[2] = bTranslate[Hash2.c[2]];
        Hash.c[3] = bTranslate[Hash2.c[3]];
    }
    return Hash.dw;
}

经过这个函数产生的值,根据其低6位就是最终的数组行号(即相当于模64)。

由于解决冲突的方法是:对同一个哈希地址提供7个位置空间。于是呈现在我们眼前是实际上就是一个横向7列、纵向64行的表结构:
位置0 位置1 位置2 …… 位置6
哈希地址0          
1          
         
         
63          

从这样的表结构中,我们知道这个哈希表以64为模。每个表允许7个相同值,它们按顺序排列在一起。所以每个哈希表结构可以索引448(64×7)个条目。

下面就是每个元素的结构:
复制  保存
struct HASH_ITEM
{
    DWORD dwHash;  //哈希值,注意最后6位为0
    DWORD dwOffset; //指向的实体中的记录部分的偏移
                 //偏移以index.dat文件第0字节为基地址。
};

我们注意到了:数组元素的哈希值的低6为0。于是系统也是利用了这个特征,将这6位数用作了每个元素的格式表示:
复制  保存
#define HASH_BIT_NOTURL   0x0001  // 位0
#define HASH_BIT_LOCK      0x0002  //位1
#define HASH_BIT_REDIR     0x0004  //位2
#define HASH_BIT_HASGRP   0x0008  //位3
#define HASH_BIT_MULTGRP  0x0010  //位4
#define HASH_BIT_RESERVED 0x0020  //位5
 
// 上面的哈希值组合
#define HASH_UNLOCKED      0  // URL条目,没被锁定
#define HASH_FREE            1  // 空闲项,以前曾被使用过
#define HASH_LOCKED         2  // URL条目, 已锁定
#define HASH_END             3  // 空闲项,没被使用过
#define HASH_UNLOCKED_SLASH  4  // URL entry, not locked, trailing slash redir
#define HASH_REDIR           5  // redirect entry
#define HASH_LOCKED_SLASH   6  // URL entry, locked, trailing slash redir
#define HASH_FLAG_MASK       7  // illegal, used to mask out hash flags


2.2 URL条目

URL条目是使用的最多的条目。它的结构和LEAK条目的结构相同,如下:
复制  保存
struct IE5_URL_FILEMAP_ENTRY : FILEMAP_ENTRY
{
    LONGLONG LastModifiedTime;       //最后修改时间
    LONGLONG LastAccessedTime;      //最后访问时间
    DWORD    dostExpireTime;         //到期时间
    DWORD    dostPostCheckTime;
 
    DWORD    dwFileSize;              //硬盘缓存中的文件的大小
    DWORD    dwRedirHashItemOffset;  // ask DanpoZ
    DWORD    dwGroupOffset;
    union
    {
        DWORD  dwExemptDelta;   // for SIG_URL
        DWORD  dwNextLeak;      // for SIG_LEAK
    };
    
    DWORD    CopySize;         // 好像总是0x60
    DWORD    UrlNameOffset;   // URL名称偏移。基地址是本URL条目的开始地址
    BYTE     DirIndex;           // 属于的子文件夹索引
    BYTE     bSyncState;        // automatic sync mode state
    BYTE     bVerCreate;        // 建立本ENTRY的CACHE的版本
    BYTE     bVerUpdate;        // 升级本ENTRY的CACHE的版本
        
DWORD    InternalFileNameOffset; //硬盘上文件名(不包括目录)字符串的偏移,
                                     //基地址是本URL条目的开始地址。
    DWORD    CacheEntryType;        //缓存类型
    DWORD    HeaderInfoOffset; //从WEB服务器中取本文件时的返回的HTTP头部信息
    DWORD    HeaderInfoSize;  //和大小(注意包括最后的回车换行的)
    DWORD    FileExtensionOffset;    // should be WORD
    DWORD    dostLastSyncTime;       
    DWORD    NumAccessed;            // 存取次数(点击率)
    DWORD    NumReferences;          // 引用次数
    DWORD    dostFileCreationTime;   // 好像是ULONG?
};


2.4 REDIR结构:
复制  保存
struct REDIR_FILEMAP_ENTRY : FILEMAP_ENTRY
{
    DWORD dwItemOffset;  // offset to hash table item of destination URL
    DWORD dwHashValue;   // destination URL hash value (BUGBUG: collisions?)
    char  szUrl[4];      // original URL, can occupy more bytes
};


2.5 GLIST结构:
复制  保存
struct LIST_FILEMAP_ENTRY : FILEMAP_ENTRY
{
    DWORD dwNext; // offset to next element in list
    DWORD nBlock; // sequence number for this block
};


三.显示系统缓存信息
 
上面就是一个完整的index.dat文件的结构,利用这些结构我们就可以写出一个完整显示系统缓存信息的程序。这项非常琐碎的工作,于是微软专门提供了一个函数库——WinInet。利用这个库中的函数,程序员可以相当方便地取出系统中缓存中的信息。
 
关于WinInet库的使用方法网络上有很多文章,大家可以参阅。
 
1.  Exploring the URL Cache  (http://www.codeproject.com/shell/urlexplr.asp
2.  Reading the Internet Explorer Cache (http://www.codeproject.com/system/IECache.asp
 

四.工作原理
 
上面我们分析了index.dat文件的结构,那么系统在什么时候读写这个文件的信息呢?
 

1.COOKIES存取
 
在用户用IE浏览器上网时,当开始输入一个网址后,IE会根据输入的网址、用户名等信息组成一个字符串,将这个字符串作为参数到哈希函数中产生一个哈希值,然后查找具体的URL实体。如果能够找到,那么IE就会具体分析此URL实体指定的COOKIES.TXT文件,看是否已经过期,若已经过期则删除;否则将在IE生成的HTTP请求报文中加上一个cookies:××××××(×××就是.txt文件中的信息)这样的请求头部。
 
在IE浏览器收到的HTTP响应报文中若响应头部中包含有Set-cookies:×××××信息时,此时IE就会将这个COOKIES值保存在一个.txt文件中,并在index.dat文件中建立一个索引值。
 

2.临时的缓存文件存取
 
临时缓存文件是一种客户端缓存技术,它有利于节省网络带宽资源并能加快浏览速度。每次使用IE浏览器上网时,IE会发送一个请求报文要求传输一个文件(比如.htm文件、.jpg文件、.css文件等等)。WEB服务器响应请求,将所要求的文件传输给IE.。IE在显示这个文件的同时,会将它放到缓存目录中,并在Index.dat文件中添加索引。
 
等下次,IE要求传输相同的文件时,IE便会在index.dat中找到这个文件的记录了(当然,如果根本没有传输下载过,index.dat中是不会找到这个记录的)。IE先检查这个文件是否已经过期了(WEB服务器会在响应某些文件请求时,在HTTP响应报文中添加一个响应头部Age:×××××来明确表示这个文件在客户机上保存的时间)。如果没有过期,IE便会直接利用这个缓冲文件而不会发送HTTP请求报文的。
 
如果没有明确的过期时间或者已经过期来,IE便会在发送的HTTP请求报文中加上一条请求头部If_modified-since:××××。而WEB服务器发现所要求的文件并没有改变,它便会发送一个304 Not Modified报文,而不再传输文件了。
 

3.历史记录
 
历史记录只是用来保存曾经浏览过的网页的网址。它并不保存其他的一些信息。也不和发送/接受HTTP协议有关。所以比较简单。
 

五.举例说明
 
理论说了很多,下面来举一个例子。通过这个例子我们看看系统是这样使用使用index.dat来索引缓存的以及系统是怎样使用缓存的。
 

1.环境
 
一台装有WEB浏览器的客户机,一台IP地址为90.0.0.6的IIS5的WEB服务器。服务器有一个名为test.asp的网页。test.asp包含一张图,并会设置一个cookies。
 

2.第一次调用网页
 
过程如下图所示:
单击显示全图,Ctrl+滚轮缩放图片

具体的HTTP报文如下:

请求报文

回应报文

GET /test.asp HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-

powerpoint, application/msword, */*

Accept-Language: en

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)

Host: 90.0.0.6

Connection: Keep-Alive

HTTP/1.1 200 OK

Server: Microsoft-IIS/5.0

Date: Thu, 26 Oct 2006 06:43:45 GMT

X-Powered-By: ASP.NET

Content-Length: 903

Content-Type: text/html

Set-Cookie: name=xiaoming; expires=Wed, 30-May-2007 16:00:00 GMT; path=/

Set-Cookie: ASPSESSIONIDASARBACA=NOMPFILDEICPMBJBKCDGKGDC; path=/

Cache-control: private

GET /img/1.gif HTTP/1.1

Accept: */*

Referer: http://90.0.0.6/test.asp

Accept-Language: en

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)

Host: 90.0.0.6

Connection: Keep-Alive

Cookie: name=xiaoming; ASPSESSIONIDASARBACA=NOMPFILDEICPMBJBKCDGKGDC

HTTP/1.1 200 OK

Server: Microsoft-IIS/5.0

X-Powered-By: ASP.NET

Date: Thu, 26 Oct 2006 06:43:45 GMT

Content-Type: image/gif

Accept-Ranges: bytes

Last-Modified: Sun, 15 Oct 2006 15:54:58 GMT

ETag: "075bc4372f0c61:19f8"

Content-Length: 66806


我们再来看一下,index.dat文件有什么变化呢?

1)临时缓存文件

首先我们计算1.gif文件的HASH值。URL名称为:http://90.0.0.6/img/1.gif ,经过上文的HashKey计算得出结果:0x127F5346。于是我们在第一个HASH表的0X5000 + 8 ×7 × (0x127F5346 & 0x3F)= 0x5150 开始查找:
00005150h: 01 00 00 00 00 9F 03 00 01 00 00 00 00 FD 03 00 ; .....?......?.
00005160h: 40 53 7F 12 80 66 00 00 40 E7 8F A7 80 F2 01 00 ; @S.€f..@鐝?.
00005170h: C0 68 1D 59 80 1B 03 00 01 00 00 00 00 48 03 00 ; 纇.Y€........H..
00005180h: 01 00 00 00 00 6C 0E 00 01 00 00 00 00 93 03 00 ; .....l.......?.
00005190h: 01 00 00 00 00 B6 03 00 C0 48 BE F4 00 D0 00 ; .....?.繦爵.?

发现5160h处就是我们要找的HASH_ITEM。于是我们在0X6680处找到我们要找的URL条目。
00006680h: 55 52 4C 20 03 00 00 00 00 75 BC 43 72 F0 C6 01 ; URL .....u糃r鹌.
00006690h: 50 AC 0D 1D CC F8 C6 01 00 00 00 00 00 00 00 00 ; P?.跳?........
000066a0h: F6 04 01 00 00 00 00 00 00 00 00 00 00 00 00 00 ; ?..............
000066b0h: 60 00 00 00 68 00 00 00 05 01 10 10 84 00 00 00 ; `...h.......?..
000066c0h: 41 00 00 00 90 00 00 00 82 00 00 00 00 00 00 00 ; A...?..?......
000066d0h: 5A 35 49 37 02 00 00 00 00 00 00 00 5A 35 02 35 ; Z5I7........Z5.5
000066e0h: 00 00 00 00 0D F0 AD 0B 68 74 74 70 3A 2F 2F 39 ; .....瓠.http://9
000066f0h: 30 2E 30 2E 30 2E 36 2F 69 6D 67 2F 31 2E 67 69 ; 0.0.0.6/img/1.gi
00006700h: 66 00 AD 0B 31 5B 31 5D 2E 67 69 66 00 F0 AD 0B ; f.?1[1].gif.瓠.
00006710h: 48 54 54 50 2F 31 2E 31 20 32 30 30 20 4F 4B 0D ; HTTP/1.1 200 OK.
00006720h: 0A 58 2D 50 6F 77 65 72 65 64 2D 42 79 3A 20 41 ; .X-Powered-By: A
00006730h: 53 50 2E 4E 45 54 0D 0A 43 6F 6E 74 65 6E 74 2D ; SP.NET..Content-
00006740h: 54 79 70 65 3A 20 69 6D 61 67 65 2F 67 69 66 0D ; Type: image/gif.
00006750h: 0A 45 54 61 67 3A 20 22 30 37 35 62 63 34 33 37 ; .ETag: "075bc437
00006760h: 32 66 30 63 36 31 3A 31 39 66 38 22 0D 0A 43 6F ; 2f0c61:19f8"..Co
00006770h: 6E 74 65 6E 74 2D 4C 65 6E 67 74 68 3A 20 36 36 ; ntent-Length: 66
00006780h: 38 30 36 0D 0A 0D 0A 7E 55 3A 71 67 6D 69 73 0D ; 806....~U:qgmis.
00006790h: 0A 00 AD 0B 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B ; ..?.瓠..瓠..瓠.
000067a0h: 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B ; .瓠..瓠..瓠..瓠.
000067b0h: 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B ; .瓠..瓠..瓠..瓠.
000067c0h: 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B ; .瓠..瓠..瓠..瓠.
000067d0h: 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B ; .瓠..瓠..瓠..瓠.
000067e0h: 0D F0 AD 0B 0D F0 AD 0B 0D F0 AD 0B 0D F0 ; .瓠..瓠..瓠..
分析这个结构,FILEMAP_ENTRY分析如下:
地址 成员 说明
00006680h dwSig 55 52 4C 20 URL
00006684h nBlocks 02 00 00 00 此条目占据2×128=256个字节

IE5_URL_FILEMAP_ENTRY分析如下:
地址 成员 说明
00006680h LastModifiedTime 75 BC 43 72 F 0 C 6 01 最后修改时间:2006-10-15  11 :54:58 PM
  LastAccessedTime 50 AC 0D 1D CC F8 C6 01 最后存取时间:2006-10-26  02 :58:17 PM
  dostExpireTime 00 00 00 00  
  dostPostCheckTime 00 00 00 00  
  dwFileSize F6 04 01 00 硬盘缓存的文件大小0x104F6
  dwRedirHashItemOffset 00 00 00 00  
  dwGroupOffset 00 00 00 00  
  dwExemptDelta 00 00 00 00  
  CopySize 60 00 00 00  
  UrlNameOffset 68 00 00 00 URL 地址保存在偏移为0X68即0X66E8的位置处。 (http://90.0.0.6/img/1.gif)
  DirIndex 05 硬盘文件子目录序号为:05
  bSyncState 01  
  bVerCreate 10  
  bVerUpdate 10  
  InternalFileNameOffset 84 00 00 00 硬盘缓存文件名保存在偏移为0X84即0X6704的位置处。 (1[1].gif)
  CacheEntryType 41 30 00 00  
  HeaderInfoOffset 90 00 00 00 HTTP 首部信息保存在偏移为0X90即0X6710的位置处。 (HTTP/1.1 200 OK X-Powered-By: ASP.NET Content-Type: image/gif ETag: "075bc4372f0c61:19f8" Content-Length: 66806   ~U:qgmis )
  HeaderInfoSize 82 00 00 00 HTTP 首部信息大小。
  FileExtensionOffset 00 00 00 00  
  dostLastSyncTime 5A 35 49 37 最后同步时间为: 2006-10-26  02 :58:18 PM
  NumAccessed 02 00 00 00 存取3次
  NumReferences 00 00 00 00  
  dostFileCreationTime 5A 35 02 35 文件建立时间

我们用同样的方法分析test.asp在index.dat中保存成test[1].htm的索引信息。同样也可以分析cookies的index.dat的索引信息。

经过了一次访问后,IE会将所有的访问过的文件放入缓存中,并在index.dat作索引。待第二次访问同样的网页时,将会出现什么情况呢?

3.第二此调用网页

当我们再次浏览这个网页的时候。我们来看看发生了什么情况。
单击显示全图,Ctrl+滚轮缩放图片

下面是它们的HTTP报文信息。

请求报文

回应报文

GET /test.asp HTTP/1.1

Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*

Accept-Language: en

Accept-Encoding: gzip, deflate

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)

Host: 90.0.0.6

Connection: Keep-Alive

Cookie: name=xiaoming

HTTP/1.1 200 OK

Server: Microsoft-IIS/5.0

Date: Thu, 26 Oct 2006 07:01:33 GMT

X-Powered-By: ASP.NET

Content-Length: 903

Content-Type: text/html

Set-Cookie: name=xiaoming; expires=Wed, 30-May-2007 16:00:00 GMT; path=/

Set-Cookie: ASPSESSIONIDASARBACA=OOMPFILDPDCEKPECJOOCPJEP; path=/

Cache-control: private

GET /img/1.gif HTTP/1.1

Accept: */*

Referer: http://90.0.0.6/test.asp

Accept-Language: en

Accept-Encoding: gzip, deflate

If-Modified-Since: Sun, 15 Oct 2006 15:54:58 GMT

If-None-Match: "075bc4372f0c61:19f8"

User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)

Host: 90.0.0.6

Connection: Keep-Alive

Cookie: name=xiaoming; ASPSESSIONIDASARBACA=OOMPFILDPDCEKPECJOOCPJEP

HTTP/1.1 304 Not Modified

Server: Microsoft-IIS/5.0

Date: Thu, 26 Oct 2006 07:01:33 GMT

X-Powered-By: ASP.NET

ETag: "075bc4372f0c61:19f8"

Content-Length: 0


我们发现第二次访问时,1.gif文件根本不需要再次传输。因为服务器端这个文件根本没有变化过。于是IE就直接从index.dat索引文件中找到1.gif文件保存在硬盘上的位置后,就直接使用它了——这就是系统使用缓存的最终目的了。


4.题外话

说说上面这些报文的一些题外话。

1)  每次请求一个ASP网页时,WEB服务器都会回应一个有ASPSEEIONID×××的cookies报文,ASP.DLL就是使用这个ASPSESSIONID来管理Session对象的——即使我们在asp文件中根本就没有使用这个对象。

2)  每次这个ASPSESSSIONID不会保存在硬盘上,它是存在IE浏览器的内存中,并且有时间期限。关闭IE或者过期后,将不会再在下次请求报文中包含这个ASPSESSIONID cookies值。于是WEB服务器又返回和一个原来不同的新的SESSIONID值。


六.总结

本文主要剖析了Windows中用来索引缓存文件、cookies文件和上文记录的Index.dat文件,并给了例题。本文主要在分析微软代码的基础的得出的,但是对于index.dat文件中的一些结构中的特殊字段不能正确得出其含义,非常遗憾,希望有爱好者能完成。
posted on 2008-08-17 10:06  ct  阅读(1411)  评论(0编辑  收藏  举报