Please see the code below:
package main
import "net"
import "log"
import "bufio"
import "time"
func main() {
l,_:=net.Listen("tcp", ":8888")
for {
conn, _ := l.Accept()
log.Println("get conn", conn.RemoteAddr())
go func() {
f, _:=conn.(*net.TCPConn).File()
d:=f.Fd()
log.Println(d)
f.Close()
arr := make([]byte, 1000)
reader := bufio.NewReader(conn)
time.AfterFunc(3*time.Second, func() {
log.Println("close conn", conn.RemoteAddr())
conn.Close()
})
for {
size, err := reader.Read(arr)
if err != nil {
break
}
log.Println("sss", arr[:size])
}
}()
}
}
when the program start,I use telnet to connect the localhost:8888,after 3 seconds,the server will kill me out, but the socket status is still ESTABLISHED when I use netstat to watch.If I remove the File() function, the socket can be closed normally.How can I fix this?
This is caused by the FDs being put into blocking mode. Once that happens, you're no longer using the runtime network poller, and have to use the socket as if you were using blocking calls and multiple threads. Underneath, a blocking recv call on a socket can't be interrupted by a close in another thread.
A workaround may be to force the FD back into non-blocking mode before closing it:
syscall.SetNonblock(int(d), true)
f.Close()
You can also shutdown the socket for reading before calling close:
conn.CloseRead()
conn.Close()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With