Go package syscall conn.Read()是非阻塞的并导致高CPU使用率

时间:2013-05-13 07:35:59

标签: networking tcp network-programming go system-calls

奇怪的是,在我的情况下,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()拨打电话?

我已研究过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)))的含义。

1 个答案:

答案 0 :(得分:8)

您没有正确处理TCP。当conn.Read()返回0字节读取时,这意味着对等体已正常关闭TCP连接。在这种情况下,您应该关闭TCP连接的末尾。

(注意这对Go来说并不特殊,read()/ recv()在TCP连接上返回0或多或少普遍意味着另一端已关闭连接)