这实际上是对这个问题的一个后续行动:How to know TCP connection is closed in Golang net package?并没有试图找出原因 .

我的想法是,我有一个接受TCP连接的服务器,并等待客户端关闭它们 . 它等待5秒,并且每秒尝试从TCP连接读取,如果这给出了EOF错误,则表明客户端已关闭连接 .

这是服务器代码:

func server(done chan bool) {
    l, _ := net.Listen("tcp", serverAddress)

    // Listen for incomming TCP connections
    conn, err := l.Accept()
    if err != nil {
        log.Fatalf("l.Accept(): got error on accept: %v", err)
    }
    defer conn.Close()

    // Read periodically from the TCP connection to see if we can find
    // out when the client has closed his end.
    go func() {
        for {
            conn.SetReadDeadline(time.Now().Add(10 * time.Millisecond))
            b, err := conn.Read([]byte{})
            fmt.Printf("Read %v bytes with err %v \n", b, err)
            if err == io.EOF {
                conn.Close()
                conn = nil
                break
            } else {
                var zero time.Time
                conn.SetReadDeadline(zero)
            }
            time.Sleep(1 * time.Second)
        }
        done <- true
    }()

    // Do this for 5 seconds, than quit
    time.Sleep(5 * time.Second)
    done <- true
}

因此客户端 Build 连接,等待两秒钟然后关闭它 . 客户代码如下:

func main() {
    done := make(chan bool, 1)
    go server(done)

    // Give the listener some time to set up
    time.Sleep(200 * time.Millisecond)

    // Dial the server
    conn, err := net.Dial("tcp", serverAddress)
    if err != nil {
        log.Fatalf("net.Dial(): got %v, want no error", err)
    }
    defer conn.Close()

    go func() {
        // After two seconds, close the TCP connection to the server
        time.Sleep(2 * time.Second)
        fmt.Printf("Client closes conn now with err %v\n", conn.Close())
    }()

    // Wait untill server is done
    <-done
}

在客户端关闭连接后,我希望服务器在读取时会出现EOF错误,但是我得到的输出是:

Read 0 bytes with err <nil> 
Read 0 bytes with err <nil> 
Client closes conn now with err <nil>
Read 0 bytes with err <nil> 
Read 0 bytes with err <nil> 
Read 0 bytes with err <nil>

我在这里有wireshark输出 . 它实际上显示FIN是由客户端发送的(包11),但只有3秒钟后服务器发送它自己的FIN:Wireshark output

所以基本上我无法弄清楚为什么我没有在服务器端读取任何错误 .