2014-09-25 86 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