我用抓包軟件抓了http的包,發現accept大多數有兩種情況。
第二種:Accept: */*5 {: e, A: _6 ? h
這兩種形式有什么區別呢?而且這兩種形式都有*/*,為什么第一種形式還要加入其他的格式呢?
沒抓過HTTP的包,你試着把完整包發上來看看,配上當時操作說明。
不過我認為是下載文件(第二種數據包)和瀏覽網頁(第一種數據包)的不同。
HTTP協議的頭信息詳解
HTTP(HyperTextTransferProtocol)是超文本傳輸協議的縮寫,它用於傳送WWW方式的數據,關於HTTP 協議的詳細內容請參 考RFC2616。HTTP協議采 用了請求/響應模型。客戶端向服務器發送一個請求,請求頭包含請求的方法、URI、協議版本、以及包含請求修飾符、客戶 信息和內容的類似於MIME的消息結構。服務器以一個狀態行作為響應,相應的內容包括消息協議的版本,成功或者錯誤編碼加上包含服務器信息、實體元信息以 及可能的實體內容。
通常HTTP消息包括 客戶機向服務器的請求消息和服務器向客戶機的響應消息。這兩種類型的消息由一個起始行,一個或者多個頭域,一個只是頭域結束的空行和可 選的消息體組成。HTTP的頭域包括通用頭,請求頭,響應頭和實體頭四個部分。每個頭域由一個域名,冒號(:)和域值三部分組成。域名是大小寫無關的,域 值前可以添加任何數量的空格符,頭域可以被擴展為多行,在每行開始處,使用至少一個空格或制表符。 / W$ \7 ~2 w5 l. r
通用頭域 5 @2 O% _3 a" A. f* u
通用頭 域包含請求和響應消息都支持的頭域,通用頭域包含Cache-Control、 Connection、Date、Pragma、Transfer-Encoding、Upgrade、Via。對通用頭域的擴展要求通訊雙方都支持此擴 展,如果存在不支持的通用頭域,一般將會作為實體頭域處理。下面簡單介紹幾個在UPnP消息中使用的通用頭域。 1 }% d# [5 z8 |
6 U* k0 ?* A/ a9 T
Cache-Control頭域
. V H {0 A+ G# M* T7 @4 N) t
Cache -Control指定請求和響應遵循的緩存機制。在請求消息或響應消息中設置 Cache-Control並不會修改另一個消息處理過程中的緩存處理過程。請求時的緩存指令包括no-cache、no-store、max-age、 max-stale、min-fresh、only-if-cached,響應消息中的指令包括public、private、no-cache、no- store、no-transform、must-revalidate、proxy-revalidate、max-age。各個消息中的指令含義如 下: + F3 Z2 m( e2 z
Public指示響應可被任何緩存區緩存。
$ r" p0 @9 l2 u6 ^6 o
Private指示對於單個用戶的整個或部分響應消息,不能被共享緩存處理。這允許服務器僅僅描述當用戶的部分響應消息,此響應消息對於其他用戶的請求無效。
no-cache指示請求或響應消息不能緩存 / _6 x+ d* Z! k9 R9 P# `7 \
( V9 {6 M) v5 g# Z' l
no-store用於防止重要的信息被無意的發布。在請求消息中發送將使得請求和響應消息都不使用緩存。 0 j) U4 q/ i4 ^* R0 j3 Y
max-age指示客戶機可以接收生存期不大於指定時間(以秒為單位)的響應。 h! t+ ]# L$ v
min-fresh指示客戶機可以接收響應時間小於當前時間加上指定時間的響應。 ) w% m) f1 M# Y) i& H( m" @# M
max-stale指示客戶機可以接收超出超時期間的響應消息。如果指定max-stale消息的值,那么客戶機可以接收超出超時期指定值之內的響應消息。
Date頭域
Date頭域表示消息發送的時間,時間的描述格式由rfc822定義。例如,Date:Mon,31Dec200104:25:57GMT。Date描述的時間表示世界標准時,換算成本地時間,需要知道用戶所在的時區。
Pragma頭域
Pragma頭域用來包含實現特定的指令,最常用的是Pragma:no-cache。在HTTP/1.1協議中,它的含義和Cache- Control:no-cache相同。 , z% ?+ h4 {5 b. m8 ~8 H! b& V
6 X0 ^& x$ R! b3 ] m
請求消息
請求消息的第一行為下面的格式: ' K1 H4 X" ^! a
MethodSPRequest-URISPHTTP-VersionCRLFMethod 表示對於Request-URI完成的方法,這個字段是大小寫敏感的,包括OPTIONS、GET、HEAD、POST、PUT、DELETE、 TRACE。方法GET和HEAD應該被所有的通用WEB服務器支持,其他所有方法的實現是可選的。GET方法取回由Request-URI標識的信息。 HEAD方法也是取回由Request-URI標識的信息,只是可以在響應時,不返回消息體。POST方法可以請求服務器接收包含在請求中的實體信息,可 以用於提交表單,向新聞組、BBS、郵件群組和數據庫發送消息。
SP表示空格。 Request-URI遵循URI格式,在此字段為星 號(*)時,說明請求並不用於某個特定的資源地址,而是用於服務器本身。HTTP- Version表示支持的HTTP版本,例如為HTTP/1.1。CRLF表示換行回車符。請求頭域允許客戶端向服務器傳遞關於請求或者關於客戶機的附加 信息。請求頭域可能包含下列字段Accept、Accept-Charset、Accept- Encoding、Accept-Language、 Authorization、From、Host、If-Modified-Since、If- Match、If-None-Match、If-Range、If-Range、If-Unmodified-Since、Max-Forwards、 Proxy-Authorization、Range、Referer、User-Agent。對請求頭域的擴展要求通訊雙方都支持,如果存在不支持的請 求頭域,一般將會作為實體頭域處理。
6 o2 a4 b7 ~) v4 h: z
典型的請求消息: " u; ~8 \9 V+ f: D; t9 T
GET http://download.microtool.de:80/somedata.exe 1 g$ x( e \) t, K4 J
Host: download.microtool.de + n1 I5 u7 R$ r; Q6 k3 o
Accept:*/*
Pragma: no-cache
Cache-Control: no-cache 7 A5 d7 \& y) k! k# u9 A- B
Referer: http://download.microtool.de/
User-Agent:Mozilla/4.04[en](Win95;I;Nav)
Range:bytes=554554-
6 ]! T- m6 K. `7 s
上例第一行表示HTTP客戶端(可能是瀏覽器、下載程序)通過GET方法獲得指定URL下的文件。棕色的部分表示請求頭域的信息,綠色的部分表示通用頭部分。
Host頭域
' H- K: G( v- ~' u6 p: q, v+ O
Host頭域指定請求資源的Intenet主機和端口號,必須表示請求url的原始服務器或網關的位置。HTTP/1.1請求必須包含主機頭域,否則系統會以400狀態碼返回。 3 c% J8 V: u' F; O# c5 t
9 `- u4 R4 ?8 {6 o& H
Referer頭域
Referer 頭域允許客戶端指定請求uri的源資源地址,這可以允許服務器生成回退鏈表,可用來登陸、優化cache等。他也允許廢除的或錯誤的連接由於維護的目的被 追蹤。如果請求的uri沒有自己的uri地址,Referer不能被發送。如果指定的是部分uri地址,則此地址應該是一個相對地址。 5 n1 D& S$ f. A! W/ d4 t$ J! l
Range頭域 4 w: @2 y4 y: J
Range頭域可以請求實體的一個或者多個子范圍。例如, ) e9 x+ \+ w! K9 u9 |& l
表示頭500個字節:bytes=0-499
表示第二個500字節:bytes=500-999
表示最后500個字節:bytes=-500 . |1 a. N% a, m% r, a% `( u9 I1 _
表示500字節以后的范圍:bytes=500-
第一個和最后一個字節:bytes=0-0,-1
同時指定幾個范圍:bytes=500-600,601-999
+ _4 u q1 V% [; o" ^7 R
但是服務器可以忽略此請求頭,如果無條件GET包含Range請求頭,響應會以狀態碼206(PartialContent)返回而不是以200 (OK)。 6 e, b+ e* i. d+ R
4 j: m# k) S: T
User-Agent頭域 " V i' U7 |6 X- Q
User-Agent頭域的內容包含發出請求的用戶信息。
# E+ K7 a# M3 H4 O
響應消息 + O2 y) G& p- a- O8 J! i/ P/ j4 j
2 J4 ~. x9 j3 f3 B/ ?. |+ h
響應消息的第一行為下面的格式: + r' j7 v0 z' z' x
HTTP-VersionSPStatus-CodeSPReason-PhraseCRLF 3 }9 P! a& B- s" a" `8 j
HTTP -Version表示支持的HTTP版本,例如為HTTP/1.1。Status- Code是一個三個數字的結果代碼。Reason-Phrase給Status-Code提供一個簡單的文本描述。Status-Code主要用於機器自 動識別,Reason-Phrase主要用於幫助用戶理解。Status-Code的第一個數字定義響應的類別,后兩個數字沒有分類的作用。第一個數字可 能取5個不同的值:
1xx:信息響應類,表示接收到請求並且繼續處理
* V: q1 y8 W/ K5 ?" ^! K% R
2xx:處理成功響應類,表示動作被成功接收、理解和接受 ( Y! v1 \* H/ ?; A% O
. o: T$ i$ ^& Q' b) K2 ~" S0 q
3xx:重定向響應類,為了完成指定的動作,必須接受進一步處理 9 X, l8 O" v; Z5 C
4xx:客戶端錯誤,客戶請求包含語法錯誤或者是不能正確執行
5xx:服務端錯誤,服務器不能正確執行一個正確的請求
' Z ~0 a( }9 {/ r8 |2 a* _# G
響應頭域允許服務器傳遞不能放在狀態行的附加信息,這些域主要描述服務器的信息和 Request-URI進一步的信息。響應頭域包含Age、Location、Proxy-Authenticate、Public、Retry- After、Server、Vary、Warning、WWW-Authenticate。對響應頭域的擴展要求通訊雙方都支持,如果存在不支持的響應頭 域,一般將會作為實體頭域處理。 % P5 U; x8 t# b: ?) e# F# E
典型的響應消息: * P! A* ~0 a. z! j5 ?$ a# r
HTTP/1.0200OK & L$ Z' ~6 r) q* \) B& X; G$ ^
Date:Mon,31Dec200104:25:57GMT
Server:Apache/1.3.14(Unix) + a0 s `7 T: Y4 @7 v
Content-type:text/html
Last-modified:Tue,17Apr200106:46:28GMT 2 F2 }8 w) Z$ B) d# {1 c& G9 r
Etag:"a030f020ac7c01:1e9f"
Content-length:39725426
Content-range:bytes554554-40279979/40279980
# ?) N& d2 U% D f0 Q9 r$ N: U
上例第一行表示HTTP服務端響應一個GET方法。棕色的部分表示響應頭域的信息,綠色的部分表示通用頭部分,紅色的部分表示實體頭域的信息。
Location響應頭 + n2 g- n' h- W5 D* N+ X! a
; ?* {5 I5 L! q2 B
Location響應頭用於重定向接收者到一個新URI地址。 ( b: \9 L2 B4 J) G" D- l
/ G& r3 }- D" B0 n" B3 @2 f+ }
Server響應頭 / {' y7 K U! d) G: l
Server響應頭包含處理請求的原始服務器的軟件信息。此域能包含多個產品標識和注釋,產品標識一般按照重要性排序。 9 G% a! h/ d6 H5 [
4 u* j$ i" M, k" L) q
實體 - a! n7 ] H2 g/ d) p
請求消息和響應消息 都可以包含實體信息,實體信息一般由實體頭域和實體組成。實體頭域包含關於實體的原信息,實體頭包括Allow、Content- Base、Content-Encoding、Content-Language、 Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、 Etag、Expires、Last-Modified、extension-header。extension-header允許客戶端定義新的實體 頭,但是這些域可能無法未接受方識別。實體可以是一個經過編碼的字節流,它的編碼方式由Content-Encoding或Content-Type定 義,它的長度由Content-Length或Content-Range定義。
Content-Type實體頭
Content-Type實體頭用於向接收方指示實體的介質類型,指定HEAD方法送到接收方的實體介質類型,或GET方法發送的請求介質類型 Content-Range實體頭 " d0 B8 @0 J+ z. W1 G. K3 o7 s+ g
Content-Range實體頭用於指定整個實體中的一部分的插入位置,他也指示了整個實體的長度。在服務器向客戶返回一個部分響應,它必須描述響應覆蓋的范圍和整個實體長度。一般格式:
% Q0 c7 J( M' K& z! |! \9 ]; E
Content-Range:bytes-unitSPfirst-byte-pos-last-byte-pos/entity-legth
" ~8 V) k0 ~- `. Q8 X
例如,傳送頭500個字節次字段的形式:Content-Range:bytes0- 499/1234如果一個http消息包含此節(例如,對范圍請求的響應或對一系列范圍的重疊請求),Content-Range表示傳送的范圍, Content-Length表示實際傳送的字節數。 / s. d6 V6 b" ]( d
, I/ m; a; b5 K" v; t
Last-modified實體頭
應答頭 | 說明 |
Allow | 服務器支持哪些請求方法(如GET、POST等)。 |
Content-Encoding | 文 檔的編碼(Encode)方法。只有在解碼之后才可以得到Content-Type頭指定的內容類型。利用gzip壓縮文檔能夠顯著地減少HTML文檔的 下載時間。Java的GZIPOutputStream可以很方便地進行gzip壓縮,但只有Unix上的Netscape和Windows上的IE 4、IE 5才支持它。因此,Servlet應該通過查看Accept-Encoding頭(即request.getHeader("Accept- Encoding"))檢查瀏覽器是否支持gzip,為支持gzip的瀏覽器返回經gzip壓縮的HTML頁面,為其他瀏覽器返回普通頁面。 |
Content-Length | 表 示內容長度。只有當瀏覽器使用持久HTTP連接時才需要這個數據。如果你想要利用持久連接的優勢,可以把輸出文檔寫入 ByteArrayOutputStram,完成后查看其大小,然后把該值放入Content-Length頭,最后通過 byteArrayStream.writeTo(response.getOutputStream()發送內容。 |
Content-Type | 表示后面的文檔屬於什么MIME類型。Servlet默認為text/plain,但通常需要顯式地指定為text/html。由於經常要設置Content-Type,因此HttpServletResponse提供了一個專用的方法setContentTyep。 |
Date | 當前的GMT時間。你可以用setDateHeader來設置這個頭以避免轉換時間格式的麻煩。 |
Expires | 應該在什么時候認為文檔已經過期,從而不再緩存它? |
Last-Modified | 文 檔的最后改動時間。客戶可以通過If-Modified-Since請求頭提供一個日期,該請求將被視為一個條件GET,只有改動時間遲於指定時間的文檔 才會返回,否則返回一個304(Not Modified)狀態。Last-Modified也可用setDateHeader方法來設置。 |
Location | 表示客戶應當到哪里去提取文檔。Location通常不是直接設置的,而是通過HttpServletResponse的sendRedirect方法,該方法同時設置狀態代碼為302。 |
Refresh | 表示瀏覽器應該在多少時間之后刷新文檔,以秒計。除了刷新當前文檔之外,你還可以通過setHeader("Refresh", "5; URL=http://host/path")讓瀏覽器讀取指定的頁面。 , {' W4 @7 T1 [7 P4 P 注 意這種功能通常是通過設置HTML頁面HEAD區的<META HTTP-EQUIV="Refresh" CONTENT="5;URL=http://host/path">實現,這是因為,自動刷新或重定向對於那些不能使用CGI或Servlet的 HTML編寫者十分重要。但是,對於Servlet來說,直接設置Refresh頭更加方便。 & y+ M% k) [# e 注意 Refresh的意義是“N秒之后 刷新本頁面或訪問指定頁面”,而不是“每隔N秒刷新本頁面或訪問指定頁面”。因此,連續刷新要求每次都發送一個Refresh頭,而發送204狀態代碼則 可以阻止瀏覽器繼續刷新,不管是使用Refresh頭還是<META HTTP-EQUIV="Refresh" ...>。 ) A3 R& `* i0 b, i, E1 s1 I 注意Refresh頭不屬於HTTP 1.1正式規范的一部分,而是一個擴展,但Netscape和IE都支持它。 |
Server | 服務器名字。Servlet一般不設置這個值,而是由Web服務器自己設置。 |
Set-Cookie | 設置和頁面關聯的Cookie。Servlet不應使用response.setHeader("Set-Cookie", ...),而是應使用HttpServletResponse提供的專用方法addCookie。參見下文有關Cookie設置的討論。 |
WWW-Authenticate | 客 戶應該在Authorization頭中提供什么類型的授權信息?在包含401(Unauthorized)狀態行的應答中這個頭是必需的。例如, response.setHeader("WWW-Authenticate", "BASIC realm=\"executives\"")。 注意Servlet一般不進行這方面的處理,而是讓Web服務器的專門機制來控制受密碼保護頁面的訪問(例如.htaccess)。 |
(一)初識HTTP消息頭
但凡搞WEB開發的人都離不開HTTP(超文本傳輸協議),而要了解HTTP,除了HTML本身以外,還有一部分不可忽視的就是HTTP消息頭。 + w$ k/ A: ^* @* |! G, ?# c
做過Socket編程的人都知道,當我們設計一個通信協議時,“消息頭/消息體”的分割方式是很常用的,消息頭告訴對方這個消息是干什么的,消息體告訴對 方怎么干。HTTP傳輸的消息也是這樣規定的,每一個HTTP包都分為HTTP頭和HTTP體兩部分,后者是可選的,而前者是必須的。每當我們打開一個網 頁,在上面點擊右鍵,選擇“查看源文件”,這時看到的HTML代碼就是HTTP的消息體,那么消息頭又在哪呢?IE瀏覽器不讓我們看到這部分,但我們可以 通過截取數據包等方法看到它。 4 U7 L( B, g+ N7 k& s, N& _
下面就來看一個簡單的例子:
首先制作一個非常簡單的網頁,它的內容只有一行:
<html><body>hello world</body></html>& W7 o0 p2 d' M' x J- I+ `
把它放到WEB服務器上,比如IIS,然后用IE瀏覽器請求這個頁面( http://localhost:8080/simple.htm),當我們請求這個頁面時,瀏覽器實際做了以下四項工作:
1 解析我們輸入的地址,從中分解出協議名、主機名、端口、對象路徑等部分,對於我們的這個地址,解析得到的結果如下:
協議名:http
主機名:localhost ) J6 q5 ~3 F3 \/ x8 J9 {+ m9 |
端口:8080 # U) m! b$ V7 s+ N" p
對象路徑:/simple.htm * I+ B0 N. [. F2 P
2 把以上部分結合本機自己的信息,封裝成一個HTTP請求數據包 3 S% ?! E, e, n# @" }2 f
3 使用TCP協議連接到主機的指定端口(localhost, 8080),並發送已封裝好的數據包 % D% r, i8 n" ~, {1 u6 S
4 等待服務器返回數據,並解析返回數據,最后顯示出來 & m, i! S+ u$ g5 v; ]7 F6 F/ e
由截取到的數據包我們不難發現瀏覽器生成的HTTP數據包的內容如下:
GET /simple.htm HTTP/1.1<CR>. c9 Q7 F0 Z2 t) E8 N2 ]1 ]8 h
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*<CR>4 v: q8 d) u" e I0 |
Accept-Language: zh-cn<CR>: P- U( ^; f* Y- n8 x
Accept-Encoding: gzip, deflate<CR>9 Y4 U5 ]7 a# M( E
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)<CR>
Host: localhost:8080<CR>
Connection: Keep-Alive<CR>
<CR>
為了顯示清楚我把所有的回車的地方都加上了“<CR>”,注意最后還有一個空行加一個回車,這個空行正是HTTP規定的消息頭和消息體的分界線,第一個空行以下的內容就是消息體,這個請求數據包是沒有消息體的。
消息的第一行“GET”表示我們所使用的HTTP動作,其他可能的還有“POST”等,GET的消息沒有消息體,而POST消息是有消息體的,消息體的內容就是要POST的數據。后面/simple.htm就是我們要請求的對象,之后 HTTP1.1表示使用的是 HTTP1.1協議。
第二行表示我們所用的瀏覽器能接受的Content-type,三四兩行則是語言和編碼信息,第五行顯示出本機的相關系信息,包括瀏覽器類型、操作系統信息等,很多網站可以顯示出你所使用的瀏覽器和操作系統版本,就是因為可以從這里獲取到這些信息。 9 R5 E0 ^, u( o
第六行表示我們所請求的主機和端口,第七行表示使用 Keep- Alive方式,即數據傳遞完並不立即關閉連接。
服務器接收到這樣的數據包以后會根據其內容做相應的處理,例如查找有沒有“/simple.htm”這個對象,如果有,根據服務器的設置來決定如何處理,如果是HTM,則不需要什么復雜的處理,直接返回其內容即可。但在直接返回之前,還需要加上HTTP消息頭。 ( S" j( j7 F/ H% b
服務器發回的完整HTTP消息如下: 4 V. k% I( x' I5 J% [) ^! ]
HTTP/1.1 200 OK<CR>
Server: Microsoft-IIS/5.1<CR>) `9 q5 V$ V2 `* {
X-Powered-By: ASP.NET<CR>$ x- K% K0 p! s) o& [9 C% X
Date: Fri, 03 Mar 2006 06:34:03 GMT<CR>9 H( [( I) u$ `: A$ }% _
Content-Type: text/html<CR>" t3 |1 u9 A. J7 `, W$ w- i, M+ r; G
Accept-Ranges: bytes<CR> I& o, ?( S1 {# C9 i" S2 u
Last-Modified: Fri, 03 Mar 2006 06:33:18 GMT<CR>7 w0 N) v3 B# N+ n+ ]2 z$ ~
ETag: "5ca4f75b8c3ec61:9ee"<CR>
Content-Length: 37<CR>
<CR>0 f. l7 n, w3 [, \
<html><body>hello world</body></html>% d; K+ l9 D- v$ D# }
同樣,我用“<CR>”來表示回車。可以看到,這個消息也是用空行切分成消息頭和消息體兩部分,消息體的部分正是我們前面寫好的HTML代碼。
消息頭第一行“HTTP/1.1”也是表示所使用的協議,后面的“200 OK”是HTTP返回代碼,200就表示操作成功,還有其他常見的如404表示對象未找到,500表示服務器錯誤,403表示不能瀏覽目錄等等。 ! }- j& J3 `! [* d7 D% I
第二行表示這個服務器使用的WEB服務器軟件,這里是IIS 5.1。第三行是ASP.Net的一個附加提示,沒什么實際用處。第四行是處理此請求的時間。第五行就是所返回的消息的content-type,瀏覽器 會根據它來決定如何處理消息體里面的內容,例如這里是text/html,那么瀏覽器就會啟用HTML解析器來處理它,如果是image/jpeg,那么 就會使用JPEG的解碼器來處理。 9 w5 v" p! s4 S* z8 i( ~3 ^+ f
消息頭最后一行“Content-Length”表示消息體的長度,從空行以后的內容算起,以字節為單位,瀏覽器接收到它所指定的字節數的內容以后就會認為這個消息已經被完整接收了。
/ m4 f( R( X! u: [2 O
9 A: D1 }6 B1 y5 V
理解HTTP消息頭 (二)常見的HTTP返回碼上一篇文章里我簡要的說了說HTTP消息頭的格式,注意到在服務器返回的HTTP消息頭里有一個“HTTP/1.1 200 OK”,這里的200是HTTP規定的返回代碼,表示請求已經被正常處理完成。瀏覽器通過這個返回代碼就可以知道服務器對所發請求的處理情況是什么,每一 種返回代碼都有自己的含義。這里列舉幾種常見的返回碼。
1 403 Access Forbidden如果我們試圖請求服務器上一個文件夾,而在WEB服務器上這個文件夾並沒有允許對這個文件夾列目錄的話,就會返回這個代碼。一個完整的403回復可能是這樣的:(IIS5.1)
HTTP/1.1 403 Access Forbidden" s% Q4 a& I4 E% I/ c
Server: Microsoft-IIS/5.1
Date: Mon, 06 Mar 2006 08:57:39 GMT% I1 K2 W2 z" N9 e' h2 q1 d: t
Connection: close
Content-Type: text/html
Content-Length: 172 6 e" m! f7 S7 B' J1 W: S) t( K
<html><head><title>Directory Listing Denied</title></head>: D2 H3 e$ _2 ]0 X* b, _ K
<body><h1>Directory Listing Denied</h1>This Virtual Directory does not allow contents to be listed.</body></html> S% _' L6 N$ ?
2 404 Object not found當我們請求的對象在服務器上並不存在時,就會給出這個返回代碼,這可能也是最常見的錯誤代碼了。IIS給出的404消息內容很長,除了消息頭以 外還有一個完整的說明“為什么會這樣”的網頁。APACHE服務器的404消息比較簡短,如下: * H. }6 Z1 I: u" @3 X4 |/ m7 T
HTTP/1.1 404 Not Found
Date: Mon, 06 Mar 2006 09:03:14 GMT# n" x7 F+ T( ^- d9 S
Server: Apache/2.0.55 (Unix) PHP/5.0.5
Content-Length: 291
Keep-Alive: timeout=15, max=100- b4 T7 q% E$ Y6 s
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1 7 M4 |+ ]% S4 w6 h5 \5 B
4 B, e" t. t$ c' [
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>% Y" p7 n" ?& Q
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL /notexist was not found on this server.</p>
<hr>* J+ N# e8 C7 z
<address>Apache/2.0.55 (Unix) PHP/5.0.5 Server at localhost Port 8080</address>( d5 a, i4 m2 k+ W
</body></html>
也許你會問,無論 是404還是200,都會在消息體內給出一個說明網頁,那么對於客戶端來說二者有什么區別呢?一個比較明顯的區別在於200是成功請求,瀏覽器會記錄下這 個地址,以便下次再訪問時可以自動提示該地址,而404是失敗請求,瀏覽器只會顯示出返回的頁面內容,並不會記錄此地址,要再次訪問時還需要輸入完整的地 址。
3 401 Access Denied當WEB服務器不允許匿名訪問,而我們又沒有提供正確的用戶名/密碼時,服務器就會給出這個返回代碼。在IIS中,設置IIS的安全屬性為不允許匿名訪問(如下圖),此時直接訪問的話就會得到以下返回結果:

HTTP/1.1 401 Access Denied
Server: Microsoft-IIS/5.1
Date: Mon, 06 Mar 2006 09:15:55 GMT
WWW-Authenticate: Negotiate# v% ~1 }" B+ _5 v; R% x9 @6 f/ }
WWW-Authenticate: NTLM; P( U" K3 G0 d/ G
Connection: close$ a5 L8 M0 b8 d1 B* T
Content-Length: 3964) _- p; d7 ?- U1 u
Content-Type: text/html
6 D& N+ b: g# E) U4 [6 j0 n
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html dir=ltr>
……, i$ [1 k- z5 j2 `! \' |/ o; j% Y
此時瀏覽器上給出的提示如下圖,讓我們輸入用戶名和密碼: 2 c a5 R$ z$ W8 X

因返回信息中消息體較長,只取前面兩行內容。注意,如果是用localhost來訪問本機的IIS,因IE可以直接取得當前用戶的身份,它會和服務器間直接進行協商,所以不會看到401提示。 + W) B0 E2 v) a' c4 q
當我們在輸入了用戶名和密碼以后,服務器與客戶端會再進行兩次對話。首先客戶端向服務器索取一個公鑰,服務器端會返回一個公鑰,二者都用BASE64編碼,相應的消息如下(編碼部分已經做了處理): L0 @& D. q" U h0 m
GET / HTTP/1.13 i2 B1 S1 v+ {" G8 U# h& B
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*8 b- W. \& A, U+ o& K
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: 192.168.0.55:8080
Connection: Keep-Alive' A* R+ v7 X3 i8 u1 `$ y
Authorization: Negotiate ABCDEFG…… ; o* o0 C& ~+ n1 X( X3 {
* _4 ]7 f% b$ f7 n0 R3 h
HTTP/1.1 401 Access Denied5 f1 M# S; y; X
Server: Microsoft-IIS/5.1
Date: Mon, 06 Mar 2006 09:20:53 GMT
WWW-Authenticate: Negotiate HIJKLMN……& U0 b' t* G% I0 T) N
Content-Length: 3715
Content-Type: text/html
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html dir=ltr>* k I; B" P' b+ L& e% u
……
客戶端拿到公鑰之后使用公鑰對用戶名和密碼進行加密碼,然后把加密以后的結果重新發給服務器:
GET / HTTP/1.1/ ^( g! r7 E: n' Q% _2 X) x
Accept: image/gif, image/x-xbitmap, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/vnd.ms-excel, application/vnd.ms-powerpoint, application/msword, */*. ~8 x. ?9 T- f& D( x
Accept-Language: zh-cn
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)
Host: 192.168.0.55:8080
Connection: Keep-Alive
Authorization: Negotiate OPQRST…… * J& @# t# ?# G- x
這樣,如果驗證通過,服務器端就會把請求的內容發送過來了,也就是說禁止匿名訪問的網站會經過三次請求才可以看到頁面。但因為客戶端瀏覽器已經緩存了公鑰,用同一個瀏覽器窗口再次請求這個網站上的其它頁面時就可以直接發送驗證信息,從而一次交互就可以完成了。