HTTP Keep-Alive模式


 

1、什么是Keep-Alive模式?

我們知道HTTP協議采用“請求-應答”模式,

當使用普通模式,即非KeepAlive模式時,每個請求/應答客戶和服務器都要新建一個連接,完成 之后立即斷開連接(HTTP協議為無連接的協議);

當使用Keep-Alive模式(又稱持久連接、連接重用)時,Keep-Alive功能使客戶端到服 務器端的連接持續有效,

當出現對服務器的后繼請求時,Keep-Alive功能避免了建立或者重新建立連接。

http 1.0中默認是關閉的,需要在http頭加入"Connection: Keep-Alive",才能啟用Keep-Alive;

http 1.1中默認啟用Keep-Alive,如果加入"Connection: close ",才關閉。

目前大部分瀏覽器都是用http1.1協議,也就是說默認都會發起Keep-Alive的連接請求了,所以是否能完成一個完整的Keep- Alive連接就看服務器設置情況。

 

2、啟用Keep-Alive的優點

從上面的分析來看,啟用Keep-Alive模式肯定更高效,性能更高。因為避免了建立/釋放連接的開銷;

注意:單用戶客戶端與任何服務器或代理之間的連接數不應該超過2個。

一個代理與其它服務器或代碼之間應該使用不超過2 * N的活躍並發連接。

這是為了提高HTTP響應時間,避免擁塞(冗余的連接並不能代碼執行性能的提升)。

 

3、回到我們的問題(即如何判斷消息內容/長度的大小?)

Keep-Alive模式,客戶端如何判斷請求所得到的響應數據已經接收完成(或者說如何知道服務器已經發生完了數據)?

我們已經知道 了,Keep-Alive模式發送完數據HTTP服務器不會自動斷開連接,所有不能再使用返回EOF(-1)來判斷;

(當然你一定要這樣使用也沒有辦法,可 以想象那效率是何等的低)!下面我介紹兩種來判斷方法。


3.1、使用消息首部字段Conent-Length

故名思意,Conent-Length表示實體內容長度,客戶端(服務器)可以根據這個值來判斷數據是否接收完成。

但是如果消息中沒有Conent-Length,那該如何來判斷呢?又在什么情況下會沒有Conent-Length呢?請繼續往下看……

3.2、使用消息首部字段Transfer-Encoding

當客戶端向服務器請求一個靜態頁面或者一張圖片時,服務器可以很清楚的知道內容大小,

然后通過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編碼由四部分組成: 1、<strong>0至多個chunk塊</strong> ,2、<strong>"0" CRLF </strong>,3、<strong>footer </strong>,4、<strong>CRLF</strong> <strong>.</strong> 而每個chunk塊由:chunk-size、chunk-ext(可選)、CRLF、chunk-data、CRLF組成。

4、消息長度的總結

其實,上面2中方法都可以歸納為是如何判斷http消息的大小、消息的數量。

RFC 2616 對 消息的長度總結如下:一個消息的transfer-length(傳輸長度)是指消息中的message-body(消息體)的長度。

當應用了 transfer-coding(傳輸編碼),每個消息中的message-body(消息體)的長度(transfer-length)由以下幾種情況 決定(優先級由高到低):

任何不含有消息體的消息(如1XXX、204、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 。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM