【问题标题】:Go package syscall conn.Read() is non-blocking and cause high CPU usageGo package syscall conn.Read() 是非阻塞的并导致高 CPU 使用率
【发布时间】:2013-05-07 04:27:23
【问题描述】:

奇怪的是,在我的情况下,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))) 是什么意思。

【问题讨论】:

  • 这是个坏主意:if err.Error() == "use of closed network connection"

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


【解决方案1】:

您没有正确处理 TCP。当 conn.Read() 返回读取的 0 字节时,这意味着对等方已经优雅地关闭了 TCP 连接。在这种情况下,您可能应该关闭 TCP 连接的一端。

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

【讨论】:

  • 嗯...你是对的,将continue 更改为break 效果很好
猜你喜欢
  • 2013-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多