SO_SNDBUF的影响

时间:2011-11-13 19:59:39

标签: c linux sockets setsockopt

我无法理解以下代码段的工作方式和原因:

    /* Now lets try to set the send buffer size to 5000 bytes */
    size = 5000;
    err = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,  &size, sizeof(int));
    if (err != 0) {
        printf("Unable to set send buffer size, continuing with default size\n");
    }

如果我们检查发送缓冲区的值,它确实正确设置为5000 * 2 = 10000。 但是,如果我们尝试发送超过发送缓冲区大小,它会发送所有内容。例如:

    n = send(sockfd, buf, 30000, 0);

    /* Lets check how much us actually sent */
    printf("No. of bytes sent is %d\n", n);

打印出30000。

这究竟是如何工作的?发送缓冲区大小限制为10000的事实没有任何影响吗?如果确实如此,究竟发生了什么?某种碎片?

UPDATE:如果套接字处于非阻塞模式会怎样?我尝试了以下方法:

  1. 将缓冲区大小更改为10000(5000 * 2)会导致发送16384个字节
  2. 将缓冲区大小更改为20000(10000 * 2)会导致发送30000个字节
  3. 再一次,为什么?

2 个答案:

答案 0 :(得分:12)

设置SO_SNDBUF选项对TCP和UDP的影响不同。

  • 对于UDP,这会设置数据报大小的限制,即任何更大的内容都将被丢弃。
  • 对于TCP,这只是为给定套接字设置内核缓冲区的大小(有一些舍入到页面边界和上限)。

因为看起来你在谈论TCP,所以你正在观察的效果是由套接字处于阻塞模式来解释的,所以send(2)会阻塞,直到内核可以接受你的所有数据和/或网络堆栈异步对数据进行排队并将其推送到网卡,从而释放缓冲区中的空间。

此外,TCP是流协议,它不保留任何“消息”结构。一个send(2)可以对应另一侧的多个recv(2),反之亦然。将其视为字节流。

答案 1 :(得分:4)

SO_SNDBUF配置套接字实现在内部使用的缓冲区。如果您的套接字是非阻塞的,则只能发送到配置的大小,如果您的套接字阻塞,则对您的呼叫没有限制。