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

标签 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() 成为 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/

相关文章:

c# - C#中套接字的列表或ArrayList

sockets - 为什么 skb_buffer 需要跳过 20 个字节才能在数据包输入时读取传输缓冲区?

java - 如何更改HSQLDB服务器监听的端口

java - 在Netty中实现消息依赖

java - 我的java代码经常陷入循环 "while ((line = rd.readLine()) != null) {"。如何优化代码

ios - 滚动到表格底部时表格跳动

python - 如何在 Python 中压缩字符串以将其存储在 Redis 中?

c# - 如何设置连接到主机 PC 的设备的 IP 地址? C# 窗体?

java - 重新启动 TCP 服务器

c - 调整 Linux 上 Web 服务器的接收 ACK 超时