2

「Hello World!」を 1000 回送信するとします。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;
}
4

2 に答える 2

2

完全な答えはありませんが、Linuxボックスでこれをテストしたところ、これが観察されました。

「Hello World!\n」を1 つ送信し、「0」で終わる場合。私は得る:

クライアント:

$./sendto
sent 14 bytes

ソケット "Recv-Q" には 768 バイトがあります (バイト単位である可能性が高く、ss ソースをチェックしていません):

$ ss -ul|grep 55555
UNCONN     768    0               127.0.0.1:55555                    *:*     

1000パケットを送信すると、次のようになります。

$ ./sendto 
sent 14000 bytes

Recv-Q:

$ ss -ul|grep 55555
UNCONN     213504 0               127.0.0.1:55555                    *:*       

サーバー (ctrl-c の後):

$ ./recvfrom 55555
^C
278 UDP messages received

ちなみに、213504/768 = 278 です。簡単な実験で、バッファ量を増やすためにどの設定を調整すればよいかわかりませんでした。また、受信したパケットがこのキューで多くのスペースを占める理由もわかりません。おそらくメタデータがたくさんありますか?osX と同様に、ドロップされたパケットは netstat -su に表示されます。

編集:「ソケットメモリ使用量」をより詳細に出力するss -ulmによる追加の観察:

UNCONN     213504 0               127.0.0.1:55555                    *:*       
skmem:(r213504,rb212992,t0,tb212992,f3584,w0,o0,bl0)

バッファリングされた 213504 バイトは、rb 値より 512 バイト上です。偶然ではないかもしれませんが、調べるにはカーネル ソースを読む必要があります。

1 つの UDP データグラムが osX でどれだけ占有するかを確認しましたか?

編集 2: これはまだ osX の適切な回答ではありませんが、Linux では、受信バッファーに割り当てられたカーネル メモリを増やすと、送信された 1000 パケットすべてをバッファーできることがわかりました。

少しやり過ぎですが、これらを使用しました (免責事項) バッファー値をランダムに調整すると、ネットワークとカーネルが大幅に台無しになる可能性があります):

net.core.rmem_max=1048568
net.core.rmem_default=1048568
于 2013-05-08T14:46:59.110 に答える