2014-09-25 89 views
4

假設我們有一個函數處理一個HTTP請求,是這樣的:Go中的HTTP ResponseWriter的寫入函數緩衝區是否會被緩存?

func handler(w http.ResponseWriter, r *http.Request) { 
    w.Write([]byte("first piece of data")) 
    // do something 
    w.Write([]byte("second piece of data")) 
} 

我想知道,如果要w.Write()的第一個電話是刷新到客戶端或不?

如果它被刷新,那麼我們實際上對客戶響應兩次,這很奇怪,因爲我們如何確定Content-Length在第二次調用之前寫入?

如果不刷新數據(比如數據在本地緩衝),那麼如果我們在第一次調用時寫入大量數據呢? (將堆棧溢出?)

任何解釋將不勝感激! :)

回答

5

我想知道如果第一次調用w.Write()是否刷新到客戶端?

net/http的默認ResonseWriter具有(目前4KB)大的輸出在它寫入net.Conn緩衝器。另外,OS通常會緩衝寫入套接字。所以在大多數情況下會發生某種緩衝。

如果它被刷新,那麼我們實際上響應兩次客戶端,這很奇怪,因爲我們如何在第二次調用寫入之前確定Content-Length?

那麼HTTP 1.1允許持久連接。這樣的響應通常不包括頭文件Content-Length。另外,還有HTTP預告片。

如果您的客戶端不支持HTTP 1.1和持久連接,它們將有某種讀取超時,在此期間,您可以隨意多次寫入連接;這是一個迴應。

這與TCP套接字和HTTP實現的性質有關。

如果不刷新數據(比如說數據在本地緩衝),那麼如果我們在第一次調用時寫入大量數據呢? (會堆棧溢出嗎?)

不,在堆棧上分配一個緩衝區沒有意義–緩衝區的主體將生活在堆上。如果你打你的每進程內存限制,你的應用程序會恐慌「內存不足」。

參見:

編輯回答你的問題的意見:

Chunked Transfer Encoding是HTTP 1.1規範的一部分,在HTTP不支持1.0。

編輯澄清:

只要總花費的時間你寫你的迴應的兩個部分不超過客戶的讀取時間出來,你不指定Content-Length頭,你只寫你響應,然後關閉連接。這完全可以,而不是「哈克」。

+0

HTTP的預告片都支持Go的'net/http'服務器和客戶端實現。不,沒有讀取超時的客戶端不會持續一整天。 HTTP的服務器輸出緩衝策略與HTTP無關,是的,操作系統緩衝區寫入套接字,在HTTP中是TCP套接字。你正在努力抨擊別人的答案。 – thwd 2014-09-25 14:54:47

+2

[是的,他們](https://golang.org/src/pkg/net/http/transfer.go#L32),我從現在開始會忽略你的評論。 – thwd 2014-09-25 15:01:39

+1

[請停止評論。](https://golang.org/src/pkg/net/http/response.go#L253) – thwd 2014-09-25 16:36:03