http的奇怪行为.服务器 - 为每个客户端建立三个连接



我是一个菜鸟围棋程序员。我目前正在编写一个将数据流式传输到客户端的 Web 应用程序。为了测试它是否运行良好,我编写了以下代码( streaming.go(:

package main
import (
    "fmt"
    "net"
    "net/http"
    "time"
)
func handler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("X-Content-Type-Options", "nosniff")
    fmt.Println("Client connected!")
    flusher, ok := w.(http.Flusher)
    if !ok {
        fmt.Println("ResponseWriter doesn't implement Flusher interface")
        return
    }
    closeNotifier, ok := w.(http.CloseNotifier)
    if !ok {
        fmt.Println("ResponseWriter doesn't implement CloseNotifier interface")
        return
    }
    closeNotifyChannel := closeNotifier.CloseNotify()
    for {
        fmt.Println("Sending data chunk...")
        fmt.Fprintf(w, "Chunk.")
        flusher.Flush()
        select {
        case <-closeNotifyChannel:
            goto closed
        default:
            time.Sleep(500 * time.Millisecond)
        }
    }
closed:
    fmt.Println("Client disconnected")
}
func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", handler)
    server := &http.Server{
        Addr:    "localhost:8000",
        Handler: mux,
        ConnState: func(conn net.Conn, state http.ConnState) {
            fmt.Printf("[ConnState] %v: ", conn.RemoteAddr())
            switch state {
            case http.StateNew:
                fmt.Println("StateNew")
            case http.StateActive:
                fmt.Println("StateActive")
            case http.StateIdle:
                fmt.Println("StateIdle")
            case http.StateHijacked:
                fmt.Println("StateHijacked")
            case http.StateClosed:
                fmt.Println("StateClosed")
            }
        },
    }
    server.ListenAndServe()
}

它的作用是:1. 客户端连接后,获取http.Flusherhttp.CloseNofier实例以进行http.ResponseWriter2.发送少量数据(块(,直到客户端断开连接(在此示例中,我使用了简单的字符串,"Chunk."(

这是我在Chrome浏览器中输入127.0.0.1:8000时该程序的示例输出:

[ConnState] 127.0.0.1:57226: StateNew
[ConnState] 127.0.0.1:57227: StateNew
[ConnState] 127.0.0.1:57228: StateNew
[ConnState] 127.0.0.1:57226: StateActive
Client connected!
Sending data chunk...
Sending data chunk...
Sending data chunk...
Sending data chunk...
Sending data chunk...
Sending data chunk...
Sending data chunk...
[ConnState] 127.0.0.1:57227: StateActive
Client connected!
Sending data chunk...
Sending data chunk...
Client disconnected
[ConnState] 127.0.0.1:57226: StateIdle
[ConnState] 127.0.0.1:57226: StateClosed
Sending data chunk...
Sending data chunk...
Sending data chunk...
Sending data chunk...
...(forever)

那么那些127.0.0.1:57227127.0.0.1:57228的黑客是什么?客户端连接后,它们不会立即激活,但是当我在浏览器中按ESC键时,一个会被激活。我的处理程序将数据发送到哪里?

我想知道Connection: keep-alive(似乎 Chrome 会自动为请求添加此标头(是否发生这种情况,请让我知道我错过了什么。谢谢。

我认为

你在这里没有遗漏任何东西。Chrome 可能打开了与您的服务器的多个连接,可能希望对远程服务器可能有许多并行请求。Chrome 最多可以打开 6 个与服务器的连接,以便与该服务器并行发出请求。但是,由于此处的测试中只有一个来自浏览器的GET调用,因此数据传输仅通过打开的套接字(或连接(之一进行。由于 2 个连接(套接字(未获取数据,因此它们可能会由于客户端或服务器端的空闲超时而关闭。如果您从Linux/Mac等运行该程序,则可以使用Tcpdump检查数据如何通过哪个套接字传输。或者,您也可以使用Wireshark来检查HTTP或TCP流量,这将使您清楚地了解这些套接字上发生的事情。可能是一些如下所示的 tcpdump 命令会有所帮助:

  $ sudo tcpdump -i lo0 port 8000  -s 65534 -A
    Eg. tcpdump -i <interface> port <some port> -s <max-packet-capture-size>  -A

最新更新