无法使用 net.Conn.Read 从 UNIX 套接字读取

Unable to read from UNIX socket using net.Conn.Read

我正在尝试使用 GO 与服务进行简单的 UNIX 套接字通信。为了测试,我创建了一个这样的套接字:

$ nc -vlU /tmp/sock
Bound on /tmp/sock
Listening on /tmp/sock

在 GO 中,我 net.Dial 尝试写一些东西,然后阅读。我在 nc 控制台中看到了写入的数据,所以我知道这是有效的。但是 net.Conn.Read 操作似乎是非阻塞的,并且会立即 return 且长度为零。从我读过的所有内容和我看到的例子来看,这个操作应该会阻塞。

buf := make([]byte, 0, 4096)
ctl, err := net.Dial("unix", "/tmp/sock")
for {
    ctl.Write([]byte("test write\n"))
    n, err := ctl.Read(buf)
    fmt.Printf("Len:%v, Data:%v, err:%v", n, buf, err)
}

我看到连接成功并写入了数据...

Connection received on /tmp/sock
test write
test write
test write
test write
...

但是GO控制台循环不阻塞,报告长度为零,没有错误

Len:0, Data:[], err:<nil>
Len:0, Data:[], err:<nil>
Len:0, Data:[], err:<nil>
Len:0, Data:[], err:<nil>
...

当然,如果我在 nc 控制台中输入任何内容,GO 程序输出中不会发生任何有趣的事情。

知道我做错了什么吗?

简答

buf := make([]byte, 0, 4096)

此代码使用 len=0!!!

创建一个缓冲区

照做

buf := make([]byte, 4096)

例子

这是我使用的一些示例,它们都有效。

实际上,套接字读写应该发生在two goroutines

package main

import (
    "bufio"
    "fmt"
    "io"
    "net"
    "time"
)

func main() {
    buf := make([]byte, 0, 4096)
    fmt.Println(buf)
    main03()
}

func main01() {
    // nc -vlU /tmp/sock0120
    ctl, err := net.Dial("unix", "/tmp/sock0120")
    if err != nil {
        fmt.Println(err)
        return
    }
    reader := bufio.NewReader(ctl)
    for {
        time.Sleep(time.Second)
        ctl.Write([]byte("test write\n"))
        msg, err := reader.ReadString('\n')
        fmt.Printf("Len:%v, Data:%v, err:%v\n", len(msg), msg, err)
    }
}

func main02() {
    // nc -vlU /tmp/sock0120
    buf := make([]byte, 4)
    ctl, err := net.Dial("unix", "/tmp/sock0120")
    if err != nil {
        fmt.Println(err)
        return
    }
    reader := bufio.NewReader(ctl)
    for {
        time.Sleep(time.Second)
        ctl.Write([]byte("test write\n"))
        n, err := io.ReadFull(reader, buf)
        fmt.Printf("Len:%v, Data:%v, err:%v\n", n, buf, err)
    }
}

func main03() {
    // nc -vlU /tmp/sock0120
    buf := make([]byte, 4)
    ctl, err := net.Dial("unix", "/tmp/sock0120")
    if err != nil {
        fmt.Println(err)
        return
    }
    for {
        time.Sleep(time.Second)
        ctl.Write([]byte("test write\n"))
        n, err := ctl.Read(buf)
        fmt.Printf("Len:%v, Data:%v, err:%v\n", n, buf, err)
    }
}