Why does golang http server fail with "broken pipe" when response exceeds 8kb?

I have an example webserver below, if you call curl localhost:3000 -v

then ^C

(cancel) it immediately (up to 1 second) it will report 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
            }   
    })))
}

      

Based on my debugging, I was able to conclude that this will only happen if the entire response writes more than 8192 bytes (or 8KB). If my entire answer is written less than 8192, no error broken pipe

is returned.

My question is , where is this set of limits for 8192 bytes (or 8 kilobytes)? Is this the limit in the Golang HTTP write buffer? Is it related to the answer to what is the answer? Is it only related to client curl

or browser client? How can I change this limit so that I can have a larger buffer written before the connection is closed (for debugging purposes)?

Thank!

+3


source to share


1 answer


The net/http/server.go

output buffer is set to 4<<10

, that is, 4KB.

The reason you are seeing the 8K error is because it takes at least 2 socket writes to detect a closed remote connection. The first write succeeds, but the remote host sends an RST packet. The second entry will be on a closed socket, which will return an error broken pipe

.



Depending on the socket write buffer and connection latency, it is possible that more writes can be made before the first RST packet is registered.

+7


source







All Articles