HTTP協議Keep-Alive模式詳解和HTTP頭字段總結

一、什麼是Keep-Alive模式?html

咱們知道HTTP協議採用「請求-應答」模式,當使用普通模式,即非KeepAlive模式時,每一個請求/應答客戶和服務器都要新建一個鏈接,完成 以後當即斷開鏈接(HTTP協議爲無鏈接的協議);當使用Keep-Alive模式(又稱持久鏈接、鏈接重用)時,Keep-Alive功能使客戶端到服 務器端的鏈接持續有效,當出現對服務器的後繼請求時,Keep-Alive功能避免了創建或者從新創建鏈接。web

http 1.0中默認是關閉的,須要在http頭加入"Connection: Keep-Alive",才能啓用Keep-Alive;http 1.1中默認啓用Keep-Alive,若是加入"Connection: close ",才關閉。目前大部分瀏覽器都是用http1.1協議,也就是說默認都會發起Keep-Alive的鏈接請求了,因此是否能完成一個完整的Keep- Alive鏈接就看服務器設置狀況。瀏覽器

二、啓用Keep-Alive的優勢緩存

從上面的分析來看,啓用Keep-Alive模式確定更高效,性能更高。由於避免了創建/釋放鏈接的開銷。下面是RFC 2616 上的總結:
By opening and closing fewer TCP connections, CPU time is saved in routers and hosts (clients, servers, proxies, gateways, tunnels, or caches), and memory used for TCP protocol control blocks can be saved in hosts.
HTTP requests and responses can be pipelined on a connection. Pipelining allows a client to make multiple requests without waiting for each response, allowing a single TCP connection to be used much more efficiently, with much lower elapsed time.
Network congestion is reduced by reducing the number of packets caused by TCP opens, and by allowing TCP sufficient time to determine the congestion state of the network.
Latency on subsequent requests is reduced since there is no time spent in TCP's connection opening handshake.
HTTP can evolve more gracefully, since errors can be reported without the penalty of closing the TCP connection. Clients using future versions of HTTP might optimistically try a new feature, but if communicating with an older server, retry with old semantics after an error is reported.
RFC 2616 (P47)還指出:單用戶客戶端與任何服務器或代理之間的鏈接數不該該超過2個。一個代理與其它服務器或代碼之間應該使用不超過2 * N的活躍併發鏈接。這是爲了提升HTTP響應時間,避免擁塞(冗餘的鏈接並不能代碼執行性能的提高)。服務器

三、回到咱們的問題(即如何判斷消息內容/長度的大小?)多線程

Keep-Alive模式,客戶端如何判斷請求所獲得的響應數據已經接收完成(或者說如何知道服務器已經發生完了數據)?咱們已經知道 了,Keep-Alive模式發送玩數據HTTP服務器不會自動斷開鏈接,全部不能再使用返回EOF(-1)來判斷(固然你必定要這樣使用也沒有辦法,可 以想象那效率是何等的低)!下面我介紹兩種來判斷方法。
3.一、使用消息首部字段Conent-Length併發

故名思意,Conent-Length表示實體內容長度,客戶端(服務器)能夠根據這個值來判斷數據是否接收完成。可是若是消息中沒有Conent-Length,那該如何來判斷呢?又在什麼狀況下會沒有Conent-Length呢?請繼續往下看……app

3.二、使用消息首部字段Transfer-Encodingide

當客戶端向服務器請求一個靜態頁面或者一張圖片時,服務器能夠很清楚的知道內容大小,而後經過Content-length消息首部字段告訴客戶端 須要接收多少數據。可是若是是動態頁面等時,服務器是不可能預先知道內容大小,這時就可使用Transfer-Encoding:chunk模式來傳輸 數據了。即若是要一邊產生數據,一邊發給客戶端,服務器就須要使用"Transfer-Encoding: chunked"這樣的方式來代替Content-Length。性能

chunk編碼將數據分紅一塊一塊的發生。Chunked編碼將使用若干個Chunk串連而成,由一個標明長度爲0 的chunk標示結束。每一個Chunk分爲頭部和正文兩部分,頭部內容指定正文的字符總數(十六進制的數字 )和數量單位(通常不寫),正文部分就是指定長度的實際內容,兩部分之間用回車換行(CRLF) 隔開。在最後一個長度爲0的Chunk中的內容是稱爲footer的內容,是一些附加的Header信息(一般能夠直接忽略)。 Chunk編碼的格式以下:

複製代碼

代碼以下:

Chunked-Body = *<strong>chunk </strong>
"0" CRLF
footer
CRLF
chunk = chunk-size [ chunk-ext ] CRLF
chunk-data CRLF</p><p>hex-no-zero = &lt;HEX excluding "0"&gt;</p><p>chunk-size = hex-no-zero *HEX
chunk-ext = *( ";" chunk-ext-name [ "=" chunk-ext-value ] )
chunk-ext-name = token
chunk-ext-val = token | quoted-string
chunk-data = chunk-size(OCTET)</p><p>footer = *entity-header

即Chunk編碼由四部分組成: 一、<strong>0至多個chunk塊</strong> ,二、<strong>"0" CRLF </strong>,三、<strong>footer </strong>,四、<strong>CRLF</strong> <strong>.</strong> 而每一個chunk塊由:chunk-size、chunk-ext(可選)、CRLF、chunk-data、CRLF組成。

四、消息長度的總結

其實,上面2中方法均可以概括爲是如何判斷http消息的大小、消息的數量。RFC 2616 對 消息的長度總結以下:一個消息的transfer-length(傳輸長度)是指消息中的message-body(消息體)的長度。當應用了 transfer-coding(傳輸編碼),每一個消息中的message-body(消息體)的長度(transfer-length)由如下幾種狀況 決定(優先級由高到低):
任何不含有消息體的消息(如1XXX、20四、304等響應消息和任何頭(HEAD,首部)請求的響應消息),老是由一個空行(CLRF)結束。
若是出現了Transfer-Encoding頭字段 而且值爲非「identity」,那麼transfer-length由「chunked」 傳輸編碼定義,除非消息因爲關閉鏈接而終止。
若是出現了Content-Length頭字段,它的值表示entity-length(實體長度)和transfer-length(傳輸長 度)。若是這兩個長度的大小不同(i.e.設置了Transfer-Encoding頭字段),那麼將不能發送Content-Length頭字段。並 且若是同時收到了Transfer-Encoding字段和Content-Length頭字段,那麼必須忽略Content-Length字段。
若是消息使用媒體類型「multipart/byteranges」,而且transfer-length 沒有另外指定,那麼這種自定界(self-delimiting)媒體類型定義transfer-length 。除非發送者知道接收者可以解析該類型,不然不能使用該類型。
由服務器關閉鏈接肯定消息長度。(注意:關閉鏈接不能用於肯定請求消息的結束,由於服務器不能再發響應消息給客戶端了。)
爲了兼容HTTP/1.0應用程序,HTTP/1.1的請求消息體中必須包含一個合法的Content-Length頭字段,除非知道服務器兼容 HTTP/1.1。一個請求包含消息體,而且Content-Length字段沒有給定,若是不能判斷消息的長度,服務器應該用用400 (bad request) 來響應;或者服務器堅持但願收到一個合法的Content-Length字段,用 411 (length required)來響應。

全部HTTP/1.1的接收者應用程序必須接受「chunked」 transfer-coding (傳輸編碼),所以當不能事先知道消息的長度,容許使用這種機制來傳輸消息。消息不該該夠同時包含 Content-Length頭字段和non-identity transfer-coding。若是一個消息同時包含non-identity transfer-coding和Content-Length ,必須忽略Content-Length 。

五、HTTP頭字段總結

最後我總結下HTTP協議的頭部字段。 一、 Accept:告訴WEB服務器本身接受什麼介質類型,/ 表示任何類型,type/* 表示該類型下的全部子類型,type/sub-type。 二、 Accept-Charset: 瀏覽器申明本身接收的字符集 Accept-Encoding: 瀏覽器申明本身接收的編碼方法,一般指定壓縮方法,是否支持壓縮,支持什麼壓縮方法(gzip,deflate) Accept-Language:瀏覽器申明本身接收的語言 語言跟字符集的區別:中文是語言,中文有多種字符集,好比big5,gb2312,gbk等等。 三、 Accept-Ranges:WEB服務器代表本身是否接受獲取其某個實體的一部分(好比文件的一部分)的請求。bytes:表示接受,none:表示不接受。 四、 Age:當代理服務器用本身緩存的實體去響應請求時,用該頭部代表該實體從產生到如今通過多長時間了。 五、 Authorization:當客戶端接收到來自WEB服務器的 WWW-Authenticate 響應時,用該頭部來回應本身的身份驗證信息給WEB服務器。 六、 Cache-Control:請求:no-cache(不要緩存的實體,要求如今從WEB服務器去取) max-age:(只接受 Age 值小於 max-age 值,而且沒有過時的對象) max-stale:(能夠接受過去的對象,可是過時時間必須小於 max-stale 值) min-fresh:(接受其新鮮生命期大於其當前 Age 跟 min-fresh 值之和的緩存對象) 響應:public(能夠用 Cached 內容迴應任何用戶) private(只能用緩存內容迴應先前請求該內容的那個用戶) no-cache(能夠緩存,可是隻有在跟WEB服務器驗證了其有效後,才能返回給客戶端) max-age:(本響應包含的對象的過時時間) ALL: no-store(不容許緩存) 七、 Connection:請求:close(告訴WEB服務器或者代理服務器,在完成本次請求的響應後,斷開鏈接,不要等待本次鏈接的後續請求了)。 keepalive(告訴WEB服務器或者代理服務器,在完成本次請求的響應後,保持鏈接,等待本次鏈接的後續請求)。 響應:close(鏈接已經關閉)。 keepalive(鏈接保持着,在等待本次鏈接的後續請求)。 Keep-Alive:若是瀏覽器請求保持鏈接,則該頭部代表但願 WEB 服務器保持鏈接多長時間(秒)。例如:Keep-Alive:300 八、 Content-Encoding:WEB服務器代表本身使用了什麼壓縮方法(gzip,deflate)壓縮響應中的對象。例如:Content-Encoding:gzip 九、Content-Language:WEB 服務器告訴瀏覽器本身響應的對象的語言。 十、Content-Length: WEB 服務器告訴瀏覽器本身響應的對象的長度。例如:Content-Length: 26012 十一、Content-Range: WEB 服務器代表該響應包含的部分對象爲整個對象的哪一個部分。例如:Content-Range: bytes 21010-47021/47022 十二、Content-Type: WEB 服務器告訴瀏覽器本身響應的對象的類型。例如:Content-Type:application/xml 1三、ETag:就是一個對象(好比URL)的標誌值,就一個對象而言,好比一個 html 文件,若是被修改了,其 Etag 也會別修改,因此ETag 的做用跟 Last-Modified 的做用差很少,主要供 WEB 服務器判斷一個對象是否改變了。好比前一次請求某個 html 文件時,得到了其 ETag,當此次又請求這個文件時,瀏覽器就會把先前得到的 ETag 值發送給WEB 服務器,而後 WEB 服務器會把這個 ETag 跟該文件的當前 ETag 進行對比,而後就知道這個文件有沒有改變了。 1四、 Expired:WEB服務器代表該實體將在何時過時,對於過時了的對象,只有在跟WEB服務器驗證了其有效性後,才能用來響應客戶請求。是 HTTP/1.0 的頭部。例如:Expires:Sat, 23 May 2009 10:02:12 GMT 1五、 Host:客戶端指定本身想訪問的WEB服務器的域名/IP 地址和端口號。例如:Host:rss.sina.com.cn 1六、 If-Match:若是對象的 ETag 沒有改變,其實也就意味著對象沒有改變,才執行請求的動做。 1七、 If-None-Match:若是對象的 ETag 改變了,其實也就意味著對象也改變了,才執行請求的動做。 1八、 If-Modified-Since:若是請求的對象在該頭部指定的時間以後修改了,才執行請求的動做(好比返回對象),不然返回代碼304,告訴瀏覽器 該對象沒有修改。例如:If-Modified-Since:Thu, 10 Apr 2008 09:14:42 GMT 1九、 If-Unmodified-Since:若是請求的對象在該頭部指定的時間以後沒修改過,才執行請求的動做(好比返回對象)。 20、 If-Range:瀏覽器告訴 WEB 服務器,若是我請求的對象沒有改變,就把我缺乏的部分給我,若是對象改變了,就把整個對象給我。瀏覽器經過發送請求對象的 ETag 或者 本身所知道的最後修改時間給 WEB 服務器,讓其判斷對象是否改變了。老是跟 Range 頭部一塊兒使用。 2一、 Last-Modified:WEB 服務器認爲對象的最後修改時間,好比文件的最後修改時間,動態頁面的最後產生時間等等。例如:Last-Modified:Tue, 06 May 2008 02:42:43 GMT 2二、 Location:WEB 服務器告訴瀏覽器,試圖訪問的對象已經被移到別的位置了,到該頭部指定的位置去取。例如:Location:http://i0.sinaimg.cn/dy/deco/2008/0528/sinahome_0803_ws_005_text_0.gif</a> 2三、 Pramga:主要使用 Pramga: no-cache,至關於 Cache-Control: no-cache。例如:Pragma:no-cache 2四、 Proxy-Authenticate: 代理服務器響應瀏覽器,要求其提供代理身份驗證信息。Proxy-Authorization:瀏覽器響應代理服務器的身份驗證請求,提供本身的身份信息。 2五、 Range:瀏覽器(好比 Flashget 多線程下載時)告訴 WEB 服務器本身想取對象的哪部分。例如:Range: bytes=1173546- 2六、 Referer:瀏覽器向 WEB 服務器代表本身是從哪一個 網頁/URL 得到/點擊 當前請求中的網址/URL。例如:Referer:http://www.sina.com/</a> 2七、 Server: WEB 服務器代表本身是什麼軟件及版本等信息。例如:Server:Apache/2.0.61 (Unix) 2八、 User-Agent: 瀏覽器代表本身的身份(是哪一種瀏覽器)。例如:User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.8.1.14) Gecko/20080404 Firefox/二、0、0、14 2九、 Transfer-Encoding: WEB 服務器代表本身對本響應消息體(不是消息體裏面的對象)做了怎樣的編碼,好比是否分塊(chunked)。例如:Transfer-Encoding: chunked 30、 Vary: WEB服務器用該頭部的內容告訴 Cache 服務器,在什麼條件下才能用本響應所返回的對象響應後續的請求。假如源WEB服務器在接到第一個請求消息時,其響應消息的頭部爲:Content- Encoding: gzip; Vary: Content-Encoding那麼 Cache 服務器會分析後續請求消息的頭部,檢查其 Accept-Encoding,是否跟先前響應的 Vary 頭部值一致,便是否使用相同的內容編碼方法,這樣就能夠防止 Cache 服務器用本身 Cache 裏面壓縮後的實體響應給不具有解壓能力的瀏覽器。例如:Vary:Accept-Encoding 3一、 Via: 列出從客戶端到 OCS 或者相反方向的響應通過了哪些代理服務器,他們用什麼協議(和版本)發送的請求。當客戶端請求到達第一個代理服務器時,該服務器會在本身發出的請求裏面添 加 Via 頭部,並填上本身的相關信息,當下一個代理服務器收到第一個代理服務器的請求時,會在本身發出的請求裏面複製前一個代理服務器的請求的Via 頭部,並把本身的相關信息加到後面,以此類推,當 OCS 收到最後一個代理服務器的請求時,檢查 Via 頭部,就知道該請求所通過的路由。例如:Via:1.0 236.D0707195.sina.com.cn:80 (squid/2.6.STABLE13) =============================================================================== HTTP 請求消息頭部實例: Host:rss.sina.com.cn User-Agent:Mozilla/五、0 (Windows; U; Windows NT 五、1; zh-CN; rv:一、八、一、14) Gecko/20080404 Firefox/二、0、0、14 Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0、9,text/plain;q=0、8,image/png,/;q=0、5 Accept-Language:zh-cn,zh;q=0、5 Accept-Encoding:gzip,deflate Accept-Charset:gb2312,utf-8;q=0、7,*;q=0、7 Keep-Alive:300 Connection:keep-alive Cookie:userId=C5bYpXrimdmsiQmsBPnE1Vn8ZQmdWSm3WRlEB3vRwTnRtW &lt;-- Cookie If-Modified-Since:Sun, 01 Jun 2008 12:05:30 GMT Cache-Control:max-age=0 HTTP 響應消息頭部實例: Status:OK - 200 -- 響應狀態碼,表示 web 服務器處理的結果。 Date:Sun, 01 Jun 2008 12:35:47 GMT Server:Apache/2.0.61 (Unix) Last-Modified:Sun, 01 Jun 2008 12:35:30 GMT Accept-Ranges:bytes Content-Length:18616 Cache-Control:max-age=120 Expires:Sun, 01 Jun 2008 12:37:47 GMT Content-Type:application/xml Age:2 X-Cache:HIT from 236-41.D07071951.sina.com.cn -- 反向代理服務器使用的 HTTP 頭部 Via:1.0 236-41.D07071951.sina.com.cn:80 (squid/2.6.STABLE13) Connection:close

相關文章
相關標籤/搜索