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

时间:2015-03-10 15:29:25

标签: 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()功能,套接字可以正常关闭。我该如何解决这个问题?

1 个答案:

答案 0 :(得分:6)

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

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

syscall.SetNonblock(int(d), true)
f.Close()

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

conn.CloseRead()
conn.Close()