【问题标题】:find out AF_UNIX + SOCK_SEQPACKET maximum message size找出 AF_UNIX + SOCK_SEQPACKET 最大消息大小
【发布时间】:2011-12-07 15:41:47
【问题描述】:

我想知道是否有可能找出SEQPACKET 的最大长度,除了实验性(a-la for( i=0; i<100...00; i++ ) send( ... );)。

还有,第二个问题:

如果我收到errno == EMSGSIZE 尝试发送AF_UNIX SEQPACKET,是否保证是因为最大消息大小,还是有其他原因?

【问题讨论】:

  • 不,这个问题就像“最大大小实际上是 130688?如果不是,可以在不重新编译内核的情况下更改它吗?”。但是我需要在 C 程序中找到最大大小,我不需要更改它的值,也不想将 130688 之类的幻数硬编码到程序中。

标签: c linux sockets unix


【解决方案1】:

限制来自变量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 的值似乎因可用的 ram 页面而异。

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

【讨论】:

  • 我的值为 212992 (= 52 * 4096)。
  • 减 32 可能是为了允许数据包头。
【解决方案2】:

在你打开socket之后,你可以用下面的代码检查一下:

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 可能是数据包标头。所以你的数据包数据可能仅限于dgram_max_size - 32

【讨论】:

    猜你喜欢
    • 2011-06-11
    • 2010-09-27
    • 2012-04-01
    • 2014-06-13
    • 1970-01-01
    • 2017-06-23
    • 2010-12-15
    • 2017-05-05
    相关资源
    最近更新 更多