这实际上是对这个问题的跟进: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
}
因此客户端建立连接,等待两秒钟然后关闭它。客户代码如下:
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
所以基本上我无法弄清楚为什么我没有在服务器端读取任何错误。