获取File()后golang tcp socket无法关闭

vze*_*zex 0 sockets tcp go

请参阅以下代码:

    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])
                             }
                     }()
             }
    }

当程序启动时,我使用telnet连接localhost:8888,3秒后,服务器会将我杀掉,但是当我使用netstat监视时套接字状态仍然是ESTABLISHED.如果我删除了File()函数,套接字可以正常关闭.我怎么解决这个问题?

Jim*_*imB 7

这是由FD进入阻塞模式引起的.一旦发生这种情况,您将不再使用运行时网络轮询器,并且必须像使用阻塞调用和多个线程一样使用套接字.在下面,recv套接字上的阻塞调用不能被close另一个线程中断.

解决方法可能是在关闭FD之前强制FD返回非阻塞模式:

syscall.SetNonblock(int(d), true)
f.Close()
Run Code Online (Sandbox Code Playgroud)

您还可以在调用close之前关闭套接字以进行读取:

conn.CloseRead()
conn.Close()
Run Code Online (Sandbox Code Playgroud)