奇怪的是,在我的例子中,Read()
是非阻塞的,导致 CPU 使用率很高。
我的代码:
在函数 main
中:
l, err := net.Listen("tcp", ":13798")
if err != nil {
log.Fatal(err)
}
for {
// Wait for a connection.
conn, err := l.Accept()
if err != nil {
log.Fatal(err)
}
// Handle the connection in a new goroutine.
// The loop then returns to accepting, so that
// multiple connections may be served concurrently.
go reqHandler.TCPHandler(conn)
runtime.Gosched()
}
函数 TCPHandler
:
func TCPHandler(conn net.Conn) {
request := make([]byte, 4096)
for {
read_len, err := conn.Read(request)
if err != nil {
if err.Error() == "use of closed network connection" {
LOG("Conn closed, error might happened")
break
}
neterr, ok := err.(net.Error);
if ok && neterr.Timeout() {
fmt.Println(neterr)
LOG("Client timeout!")
break
}
}
if read_len == 0 {
LOG("Nothing read")
continue
} else {
// do something
}
request := make([]byte, 4096)
}
}
问题是,conn.Read()
是非阻塞的,所以每次它转到 LOG("Nothing read")
然后继续,这导致高 CPU 使用率。如何使 conn.Read()
成为 block 调用?
我研究过 syscall
包,但卡在了 Syscall.Read()
因为我在我的 OS X 10.8.3 上发现了这个问题,所以这里是相关的源代码:
http://golang.org/src/pkg/syscall/zsyscall_darwin_amd64.go?h=Read#L898
我不知道 Syscall(SYS_READ, uintptr(fd), uintptr(_p0), uintptr(len(p)))
是什么意思。
最佳答案
您没有正确处理 TCP。当 conn.Read() 返回 0 字节读取时,这意味着对等方已正常关闭 TCP 连接。在这种情况下,您可能应该关闭 TCP 连接的末端。
(请注意,这对 Go 来说并不特殊,read()/recv() 在 TCP 连接上返回 0 或多或少意味着另一端已关闭连接)
关于networking - Go package syscall conn.Read() 是非阻塞的,导致 CPU 使用率高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16516948/