了解set/getsockopt SO_SNDBUF大小加倍

了解set/getsockopt SO_SNDBUF大小加倍,c,linux,sockets,C,Linux,Sockets,嗨,我有以下程序来检查UDP套接字的发送缓冲区大小。但是,我觉得返回值有点让我困惑。我使用以下简单的应用程序: #include <sys/socket.h> #include <stdio.h> int main(int argc, char **argv) { int sockfd, sendbuff; socklen_t optlen; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd == -1)

嗨,我有以下程序来检查UDP套接字的发送缓冲区大小。但是,我觉得返回值有点让我困惑。我使用以下简单的应用程序:

#include <sys/socket.h>
#include <stdio.h>

int main(int argc, char **argv)
{
 int sockfd, sendbuff;
 socklen_t optlen;

 sockfd = socket(AF_INET, SOCK_DGRAM, 0);
 if(sockfd == -1)
     printf("Error");

 int res = 0;

 // Get buffer size
 optlen = sizeof(sendbuff);
 res = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);

 if(res == -1)
     printf("Error getsockopt one");
 else
     printf("send buffer size = %d\n", sendbuff);

 // Set buffer size
 sendbuff = 98304;

 printf("sets the send buffer to %d\n", sendbuff);
 res = setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, sizeof(sendbuff));

 if(res == -1)
     printf("Error setsockopt");


 // Get buffer size
 optlen = sizeof(sendbuff);
 res = getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &sendbuff, &optlen);

 if(res == -1)
     printf("Error getsockopt two");
 else
     printf("send buffer size = %d\n", sendbuff);

 return 0;
}
我的机器上的输出是:

发送缓冲区大小=129024

将发送缓冲区设置为98304

新发送缓冲区大小=196608


有人能澄清我在这里做错了什么,或者如何解释输出吗?

你没有做错任何事。Linux在设置内核时将其值加倍,在查询时返回加倍的值。男子7说:


天哪,蝙蝠侠!这就是skbuf的所有内容:@csyangchen:我只能猜测,但我假设有人有这样的想法,通过将缓冲区设置为大小n,缓冲区应该能够容纳n字节的有效负载。因此,至少在没有连接的底层协议(如UDP)的情况下,需要额外的缓冲区大小来保存消息头。@csyangchen我还想了解更多的细节,而不是含糊不清的解释。我猜这可能与TCP的运行方式有关,例如,当缓冲区为XX字节时,也可能有相同大小的字节在向目的地传输。在远程服务器确认之前,这些字节必须保留在发送方,在最坏的情况下,如果remote的回复速度慢,并且TCP窗口比SNDBUF大,那么它可能是缓冲区的两倍。简言之:1983年的人几乎没有编写API的经验,所以如果你想使用这些恐龙,就必须处理这些无意义的事情是有道理的。可悲的是,整个互联网都是基于这些东西的,这就是为什么你最终不得不对其进行抽象,更不用说,出于同样的原因,根据平台的不同,在使用上存在着细微的差异——这是不合理的——因此,除非你用合适的接口将其包装起来,并将其隐藏起来,否则它不是一个可移植的API。 [...] SO_SNDBUF Sets or gets the maximum socket send buffer in bytes. The ker- nel doubles this value (to allow space for bookkeeping overhead) when it is set using setsockopt(), and this doubled value is returned by getsockopt(). The default value is set by the wmem_default sysctl and the maximum allowed value is set by the wmem_max sysctl. The minimum (doubled) value for this option is 2048. [...] NOTES Linux assumes that half of the send/receive buffer is used for internal kernel structures; thus the sysctls are twice what can be observed on the wire. [...]