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 十六進制 服務器 服務端 幹什麽
文章來源: