HTTP Keep-Alive模式客戶端與服務器如何斷定傳輸完成

長鏈接是什麼

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

服務器如何知道已經徹底接受客戶端發送的數據

Content-Length 是一個實體消息首部,用來指明發送給接收方的消息主體的大小,即用十進制數字表示的八位元組的數目。瀏覽器

客戶端如何知道已經徹底接受服務端發送的數據

  • 在HTTP 1.0 短鏈接中客戶端發送一個小請求,服務器響應以所指望的信息(例如一個html文件或一副gif圖像)。服務器一般在發送回所請求的數據以後就關閉鏈接。這樣客戶端讀數據時會返回EOF(-1),就知道數據已經接收徹底了。
  • 消息首部字段Conent-Length
  • 消息首部字段Transfer-Encoding

Transfer-Encoding

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

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

Transfer-Encoding 是一個用來標示 HTTP 報文傳輸格式的頭部值。儘管這個取值理論上能夠有不少,可是當前的 HTTP 規範裏實際上只定義了一種傳輸取值——chunked。工具

若是一個HTTP消息(請求消息或應答消息)的Transfer-Encoding消息頭的值爲chunked,那麼,消息體由數量未定的塊組成,並以最後一個大小爲0的塊爲結束。ui

每個非空的塊都以該塊包含數據的字節數(字節數以十六進制表示)開始,跟隨一個CRLF (回車及換行),而後是數據自己,最後塊CRLF結束。在一些實現中,塊大小和CRLF之間填充有白空格(0x20)。this

最後一塊是單行,由塊大小(0),一些可選的填充白空格,以及CRLF。最後一塊再也不包含任何數據,可是能夠發送可選的尾部,包括消息頭字段。消息最後以CRLF結尾。編碼

一個示例響應以下:code

HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25
This is the data in the first chunk

1A
and this is the second one
0

注意:htm

  • chunked 和 multipart 兩個名詞在乎義上有相似的地方,不過在 HTTP 協議當中這兩個概念則不是一個類別的。multipart 是一種 Content-Type,標示 HTTP 報文內容的類型,而 chunked 是一種傳輸格式,標示報頭將以何種方式進行傳輸。
  • chunked 傳輸不能事先知道內容的長度,只能靠最後的空 chunk 塊來判斷,所以對於下載請求來講,是沒有辦法實現進度的。在瀏覽器和下載工具中,偶爾咱們也會看到有些文件是看不到下載進度的,即採用 chunked 方式進行下載。
  • chunked 的優點在於,服務器端能夠邊生成內容邊發送,無需事先生成所有的內容。HTTP/2 不支持 Transfer-Encoding: chunked,由於 HTTP/2 有本身的 streaming 傳輸方式(Source:MDN - Transfer-Encoding)。

transfer-coding與Content-Length

其實,上面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 。

相關文章
相關標籤/搜索