发现 AF_UNIX + SOCK_SEQPACKET 的最大消息大小

7

我想知道除了试验性方法(例如 for( i=0; i<100...00; i++ ) send( ... );)之外,是否有可能找到 SEQPACKET 的最大长度。

还有第二个问题:

如果我在尝试发送 AF_UNIX SEQPACKET 时收到 errno == EMSGSIZE,那么这是否保证是由于消息大小达到了最大值,或者可能还有其他原因?


不,那个问题就像是“最大尺寸实际上是130688吗?如果不是,能否在不重新编译内核的情况下更改它?”但我需要在C程序中找到最大尺寸,我不需要更改它的值,也不想在程序中硬编码魔术数字如130688。 - grungegurunge
2个回答

12

限制来自变量sysctl_wmem_default,可以在proc文件系统中查看:/proc/sys/net/core/wmem_max

不同版本的Linux在这一点上的实现可能不同。但是对于UNIX域套接字,会有类似以下的代码:

sk->sk_sndbuf = sysctl_wmem_default;

err = -EMSGSIZE;
if (len > sk->sk_sndbuf - 32)
    goto out;

因此,实际限制是:/proc/sys/net/core/wmem_max的值减去32。 我不知道这个神奇数字在不同版本之间会有多大变化。 /proc/sys/net/core/wmem_max的值似乎会随着可用内存页数而变化。

在我的Linux系统中,该值为105472。当使用AF_UNIX和SOCK_DGRAM时,最大数据报大小为105440。 如果我尝试发送大小为105441的消息,它将失败并显示EMSGSIZE。


1
我的值是212992(= 52 * 4096)。 - johnchen902
1
减去32可能是为了留出数据包头部的空间。 - Alexis Wilke

0
刚打开套接字后,您可以使用以下代码进行检查:
int s = socket(AF_UNIX, SOCK_DGRAM, 0); // or SOCK_SEQPACKET
int dgram_max_size = 0;
socklen_t optlen = sizeof(dgram_max_size);
int r = getsockopt(s, SOL_SOCKET, SO_SNDBUF, &dgram_max_size, &optlen);
if(r != 0) {
    printf("error: can't retrieve socket max. size\n");
    exit(1);
}

对于任何套接字,在发送数据之前必须完成大小设置以确保其为最大值。对于数据报套接字,任何时候都可能有效。对于流式套接字,缓冲区在写入数据时可能会收缩,在发送数据时则会扩展。
注意:正如SKi所提到的,大小可能会误差几个字节。32可能是数据包头部。因此,您的数据包大小可能仅限于。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接