三分鐘搞懂 HTTP Transfer-Encoding

分類:IT技術 時間:2016-10-06

Transfer-Encoding 是HTTP header 中的 entity header,所謂entity header就是專門用來描述消息體(message body)的頭,像 Content-Length, Content-Language, Content-Encoding 都屬於 entity header這一類,他們分別用來描述消息體的長度、語言、編碼格式。那麽 Transfer-Encoding 是用來幹什麽的呢?

通常,HTTP Response 中的 message body 是整個包一起發送到客戶端的,Content-Length 消息頭字段就是用來表示消息體的長度, 服務端必須精確地告訴客戶端這個 message body 的長度是多少, 如果Content-Length 比實際長度短,會造成內容被截斷,如果比實體內容長,客戶端就一直處於pendding狀態,直到所有的消息體都返回了才結束請求。但是對於HTTP持久連接,服務端發送消息體之前就要提前計算出消息體的長度作為Content-Length 發送給客戶端,對於動態生成的內容在完全創建好之前是無法預知內容的長度的,這就要服務器緩沖內容直到完整的生成內容後計算出Content-Length的值才能發送給客戶端。然而使用分塊傳輸編碼(Transfer-Encoding),數據分解成一系列數據塊,並以一個或多個塊發送,這樣服務器可以發送數據而不需要預先知道發送內容的總大小,這就是Transfer-Encoding 的作用。

在消息頭中指定 Transfer-Encoding: chunked 就表示整個response將使用分塊傳輸編碼來傳輸內容,一個完整的消息體由n個塊組成,並以最後一個大小為0的塊為結束。每個非空的塊包括兩部分,分別為:塊的長度(用十六進制表示)後面跟一個CRLF (回車及換行),長度並不包括結尾的回車換行符。第二部分就是數據本身,同樣以CRLF (回車及換行)結束。最後一塊是單行,只由塊大小(0)以及CRLF組成,不包含任何數據。

現在就可以用python實現一個簡單的 HTTP Server 來指定 Response 的頭 Transfer-Encoding。

# -*- coding:utf-8 -*-

import socket

if __name__ == '__main__':
    PORT = 8000
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind(('127.0.0.1', PORT))
    sock.listen(1)
    print 'Serving HTTP on port %s ...' % PORT

    while 1:
        conn, addr = sock.accept()
        print conn, addr
        request = conn.recv(1024)
        # HTTP響應消息
        conn.sendall("HTTP/1.1 200 OK\r\n")  # status line
        conn.sendall("Content-Type: text/plain\r\n")
        conn.sendall("Transfer-Encoding: chunked\r\n")  # 分塊傳輸編碼
        conn.sendall("\r\n")  # 空行
        conn.sendall("b\r\n")  # 11個字節的長度
        conn.sendall("hello world\r\n")  # 消息體
        conn.sendall("0\r\n")  # 最後一塊0長度
        conn.sendall("\r\n")
        conn.close()

用telnet請求測試:

telnet localhost 8000
Trying ::1...
telnet: connect to address ::1: Connection refused
Trying fe80::1...
telnet: connect to address fe80::1: Connection refused
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
get HTTP/1.1 /              # 發送GET請求
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

b
hello world
0

最後引用Stack Overflow 上一句非常精辟的話作為總結:

Transfer-Encoding: chunked is needed when the total content length is unknown before the first bytes are sent.

相關參考: 一次完整的HTTP請求過程


Tags: message 十六進制 服務器 服務端 幹什麽

文章來源:


ads
ads

相關文章
ads

相關文章

ad