Linux SO_SNDBUF 的作用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/8114280/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 07:11:20  来源:igfitidea点击:

Effect of SO_SNDBUF

clinuxsocketssetsockopt

提问by Arun

I am unable to make sense of how and why the following code segments work :

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

    /* 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");
    }

If we check the value of the send buffer, it is indeed correctly set to 5000*2 = 10000. However, if we try to send more than the send buffer size, it does send all of it. For example:

如果我们检查发送缓冲区的值,它确实正确设置为 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);

This prints out 30000.

这会打印出 30000。

How exactly did this work? Didn't the fact that the send buffer size was limited to 10000 have any effect? If it did, what exactly happened? Some kind of fragmentation?

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

UPDATE:What happens if the socket is in non-blocking mode? I tried the following:

更新:如果套接字处于非阻塞模式会发生什么?我尝试了以下方法:

  1. Changing buffer size to 10000 (5000*2) causes 16384 bytes to be sent
  2. Changing buffer size to 20000 (10000*2) causes 30000 bytes to be sent
  1. 将缓冲区大小更改为 10000 (5000*2) 会导致发送 16384 字节
  2. 将缓冲区大小更改为 20000 (10000*2) 会导致发送 30000 个字节

Once again, why?

再说一遍,为什么?

采纳答案by Nikolai Fetissov

The effect of setting SO_SNDBUFoption is different for TCP and UDP.

设置SO_SNDBUF选项的效果对于 TCP 和 UDP 是不同的。

  • For UDP this sets the limit on the size of the datagram, i.e. anything larger will be discarded.
  • For TCP this just sets the size of in-kernel buffer for given socket (with some rounding to page boundary and with an upper limit).
  • 对于 UDP,这设置了数据报大小限制,即任何更大的都将被丢弃。
  • 对于 TCP,这只是为给定的套接字设置内核缓冲区的大小(对页面边界进行一些舍入和上限)。

Since it looks like you are talking about TCP, the effect you are observing is explained by the socket being in blocking mode, so send(2)blocks until kernel can accept all of your data, and/or the network stack asynchronously de-queueing data and pushing it to the network card, thus freeing space in the buffer.

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

Also, TCP is a stream protocol, it does not preserve any "message" structure. One send(2)can correspond to multiple recv(2)s on the other side, and the other way around. Treat it as byte-stream.

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

回答by Werner Henze

SO_SNDBUFconfigures the buffer that the socket implementation uses internally. If your socket is non-blocking you can only send up to the configured size, if your socket is blocking there is no limitation for your call.

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