http - HTTP ResponseWriter 的 write 函数会在 Go 中缓冲吗?

标签 http go flush

假设我们有一个处理 HTTP 请求的函数,类似于:

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() 的第一次调用是否刷新到客户端?

如果它被刷新,那么我们实际上响应了客户端两次,这很奇怪,因为我们如何在第二次调用 write 之前确定 Content-Length

如果不刷新(比如数据在本地缓冲),那么如果我们在第一次调用时写入大量数据怎么办? (那个堆栈会溢出吗?)

任何解释将不胜感激! :)

最佳答案

I'm wondering that if the first call to w.Write() is flushed to client or not?

net/http 的默认 ResonseWriter 在它写入的 net.Conn 上有一个(当前为 4KB)大输出缓冲区。此外,操作系统通常会缓冲对套接字的写入。所以在大多数情况下,会发生某种缓冲。

If it is flushed, then we actually responses to clients twice, this is strange because how can we determine Content-Length before the second call to write?

好吧,HTTP 1.1 允许持久连接。此类响应通常不包含 Content-Length header 。此外,还有 HTTP 预告片。

如果您的客户端不支持 HTTP 1.1 和持久连接,它们将有某种读取超时,在此期间您可以根据需要多次写入连接;这是一个回应。

与 Go 相比,这与 TCP 套接字和 HTTP 实现的性质有关。

If it is not flushed (say the data is buffered locally), then what if we write a huge amount of data at the first call? (will that stack overflow?)

不,在堆栈上分配缓冲区没有意义——缓冲区的主体将存在于堆上。如果您达到每个进程的内存限制,您的应用程序将出现“内存不足”的 panic 。

另见:

编辑以在评论中回答您的问题:

Chunked Transfer Encoding是 HTTP 1.1 规范的一部分,在 HTTP 1.0 中不受支持。

编辑澄清:

只要您编写响应的两个部分所花费的总时间不超过客户端的读取超时,并且您不指定 Content-Length header ,您只需编写您的响应,然后关闭连接。这完全没问题,不是“hacky”。​​

关于http - HTTP ResponseWriter 的 write 函数会在 Go 中缓冲吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26033853/

相关文章:

java - 如何通过表单上传文件并让 Java 将其作为输入流处理?

java - 如何在 ResponseEntity 中返回 CREATED 状态 (201 HTTP)

javascript - 从文件中读取json数据

c++ - 将句子作为用户的字符串输入读取

c - 在定时器 fd 上执行 lseek 时出错

xml - 哪些是 HTML 和 XML 特殊字符?

java - 如何从serversocket的accept方法中退出?

go - Golang 中带有带外预共享 key (PSK) 的 TLS

bash - 如何在Go(golang)中直接调用系统外壳?

python - sys.stdout.flush() 无法与 python 和 electronjs 一起正常工作