繁体   English   中英

O_NONBLOCK SOCK_STREAM限制为8192

[英]O_NONBLOCK SOCK_STREAM limited to 8192

我正在使用net.Listen("unix", sockname)从c程序写入正在从go程序中监听的Unix域套接字的SOCK_STREAM中。 当我使用fcntl()将套接字设置为O_NONBLOCK ,我看到C程序在第一次写入时仅写入8192字节。 失败后,我将监视并写回剩余数据,但是在这种情况下,服务器上读取的数据无效。

当我不使用O_NONBLOCK ,整个8762个字节将在一次写入中写入,并且一切都会按预期进行。

C客户端套接字连接

    if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
        return;
    }
   int flags = fcntl(fd, F_GETFL, 0);
   flags = flags|O_NONBLOCK;
   fcntl(fd, F_SETFL, flags);
   ...
    if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        return;
    }

C客户写作

        while (written < to_write) {
            int result;
            if ((result = write(fd, &buffer[written], to_write - written)) < 0) {
                if (errno == EINTR) {
                    continue;
                }
                if (errno == EAGAIN) {
                    struct pollfd pfd = { .fd = fd, .events = POLLOUT };
                    poll_count++;
                    if (poll_count > 3) {
                        goto end;
                    }
                    if ((poll(&pfd, 1, -1) <= 0) && (errno != EAGAIN)) {
                        goto end;
                    }
                    continue;
                }
end:
                return written ? written : result;
            }
            written += result;
            buffer += result;
        }

去服务器阅读

buf := make([]byte, 0, count)
var tmpsize int32
for {
    if count <= 0 {
        break
    }

    if count > 100 {
        tmpsize = 100
    } else {
        tmpsize = count
    }

    tmp := make([]byte, tmpsize)
    nr, err = conn.Read(tmp)
    if err != nil {
        return
    }

    buf = append(buf, tmp[:nr]...)
    count = count - int32(nr)
}

我在这里想念什么。 我正在OSX上运行它。 我还尝试将Go Server中的SO_SNDBUF设置为10000,但这无济于事

err = syscall.SetsockoptInt(int(fd.Fd()), syscall.SOL_SOCKET, syscall.SO_SNDBUF, 10000)
if err != nil {
    return
}

我要做的就是将数据直接读取为bytes.Buffer与此处列出的答案类似:

https://stackoverflow.com/a/24343240/8092543

https://golang.org/pkg/io/#Copy

io.Copy在于它使用了Writer + Reader接口,这很令人满意,但是您的bytes.Buffer (io.Writer)和conn.Read (io.Reader)令人满意。 用类似...的东西替换整个块

var buf bytes.Buffer
count, err := io.Copy(buf, conn)
if err != nil { 
    return nil, fmt.Errorf("error during conn read: %v", err)
}

return buf.Bytes(), nil

这是正常的行为。 无阻塞写操作只能传输与套接字发送缓冲区匹配的数据。 如果计数不足,则需要循环或选择可写性,然后重试。 另一方面,阻塞写入总是传输整个数据。

设置发送缓冲区大小在Unix域套接字上可能没有任何作用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM