我在下面有一个示例网络服务器,如果您调用curl localhost:3000 -v,然后立即^C(取消)(在1秒之前)调用它,它将报告write tcp 127.0.0.1:3000->127.0.0.1:XXXXX: write: broken pipe

package main

import (
    "fmt"
    "net/http"
    "time"
)

func main() {
    log.Fatal(http.ListenAndServe(":3000", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            time.Sleep(1 * time.Second)

            // Why 8061 bytes? Because the response header on my computer
            // is 132 bytes, adding up the entire response to 8193 (1 byte
            // over 8kb)
            if _, err := w.Write(make([]byte, 8061)); err != nil {
                    fmt.Println(err)
                    return
            }
    })))
}

根据我的调试,我可以得出结论,只有在整个响应写入8192字节(或8kb)以上的情况下,才会发生这种情况。如果我的整个响应写的少于8192,则不返回broken pipe错误。

我的问题是,这8192个字节(或8kb)的缓冲区限制在哪里设置? 这是Golang HTTP写缓冲区的限制吗?这与响应被分块有关吗?这仅与curl客户端或浏览器客户端有关吗?如何更改此限制,以便在关闭连接之前可以编写更大的缓冲区(出于调试目的)?

谢谢!

最佳答案

net/http/server.go中,输出缓冲区设置为4<<10,即4KB。

之所以会看到8KB的错误,是因为至少要写入2次套接字才能检测到关闭的远程连接。第一次写入成功,但是远程主机发送RST数据包。第二次写入将是关闭的套接字,这将返回broken pipe错误。

根据套接字写缓冲区和连接等待时间,在注册第一个RST数据包之前,可能会成功进行更多写操作。

关于http - 当响应超过8kb时,为什么golang http服务器出现 “broken pipe”失败?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43189375/

10-11 14:12