UDP 缓冲区溢出而没有填充接收缓冲区?

mar*_*ril 2 c sockets distributed udp network-programming

如果我发送 1000 个“Hello World!” UDP 消息(12 字节 + 28 IP/UDP 开销),我观察到在接收端我只缓冲 658(总是相同的数字,658*40 = 26320 字节)。我这样做,通过在服务器上睡觉时发送 UDP 消息(在创建套接字之后)。

奇怪的是,服务器上的 SO_RCVBUF 选项是 42080 字节。所以,我想知道为什么我不能缓冲 1000 条消息。你知道剩下的 15760 字节都花在哪里了吗?

在服务器代码下方(其中 distrib.h 包含套接字和信号处理函数的基本错误处理包装器):

#include "distrib.h"

static int count;
static void sigint_handler(int s) {
  printf("\n%d UDP messages received\n",count);
  exit(0);
}

int main(int argc, char **argv) 
{
  struct addrinfo* serverinfo;
  struct addrinfo hints;
  struct sockaddr_storage sender;
  socklen_t len;
  int listenfd,n;
  char buf[MAXLINE+1];

  if (argc != 2) {
    log_error("usage: %s <port>\n", argv[0]);
    exit(1);
  }

  Signal(SIGINT,sigint_handler);

  bzero(&hints,sizeof(hints));
  hints.ai_family = AF_INET;    
  hints.ai_socktype = SOCK_DGRAM; 
  hints.ai_protocol = IPPROTO_UDP;
  Getaddrinfo("127.0.0.1", argv[1], &hints, &serverinfo);

  listenfd = Socket(serverinfo->ai_family, serverinfo->ai_socktype, 
            serverinfo->ai_protocol);
  Bind(listenfd, serverinfo->ai_addr,serverinfo->ai_addrlen);
  freeaddrinfo(serverinfo);

  count =0;
  sleep(20); 
  while(true) {
    bzero(buf,sizeof(buf));
    len = sizeof(sender);
    n = Recvfrom(listenfd, buf, MAXLINE, 0, (struct sockaddr*)&sender,&len);
    buf[n]='\0';
    count++;

  }

  close(listenfd);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*odd 5

进行反向计算会提供更多信息——您的缓冲区是 42080,它在开始丢弃之前缓冲了 658 个数据包。现在 42080/658 = 63.95,所以看起来它把每个数据包计算为 64 字节,如果到目前为止缓冲的数据包的总大小等于或高于限制,则丢弃数据包。由于它缓冲整个数据包,它实际上最终缓冲略多于限制。

为什么是 64 字节而不是 40 字节?也许它包括一些排队开销,或者它可能会四舍五入到 2 的某个幂的倍数以进行对齐,或者可能是两者的某种组合。