1

演習の一環としてネットワーク スループットをテストする小さなプログラムを作成しており、(TCP のパフォーマンスを向上させるために) 送受信バッファーを 256 KB に増やす必要があります。SO_SNDBUF/SO_RCVBUF オプションを使用してこれを行ってsetsockopt()おり、「net.core.rmem_max」と「net.core.wmem_max」の値も増やしました。

getsockopt() はバッファ サイズの増加 (256KB 値の 2 倍) を確認するので、これで問題ないことがわかります。ただし、あるホストから別のホストに256KBのデータを送信すると、受信者は常に、すべてのデータを受信するまで、さまざまなサイズの複数の読み取りで受信します(受信バイト数が1448から18824の範囲の20から40の読み取りの間のどこかから)。 . この時点で、主にこれらの質問でかなり混乱しましたが、

  1. バッファサイズが大きくなったので、1回の読み取りで受け取るべきではありませんか?
  2. また、各読み取りのバイト数が大きく異なるのはなぜですか (一定である必要はありません)。
  3. 1 回の読み取りで 256KB を確実に受信する方法はありますか?

以下は、読み取り部分を示す受信側のスニペットです。

  while(1) {
    memset(&client_addr, 0, sizeof(client_addr));
    if ((connfd = accept(listenfd, (struct sockaddr*)&client_addr, &socklen)) <= 0) {
      perror("accept()");
      exit(EXIT_FAILURE);
    }

    while ((n = recv(connfd, &buff[0], BUFF_SIZE, 0/*MSG_WAITALL*/)) > 0) {
      totalBytes += n;
      ++pktCount;
      printf("Received(%d): %d bytes\n", pktCount, n);
    }

    if (n == 0) {
      printf("Connection closed (Total: %lu bytes received)\n", totalBytes);
    }

    close(connfd);
    connfd = -1;
    totalBytes = 0;
    pktCount = 0;
  }

どんな助けでも素晴らしいでしょう。

ティア

4

2 に答える 2

2

バッファサイズが大きくなったので、1回の読み取りで受け取るべきではありませんか?

いいえ。TCP/IP はストリーミング プロトコルであり、データを小さなパケットに分割します。バッファ サイズは主に、基盤となるネットワーク層の実装が使用できるメモリの量に影響します (Linux では通常、設定したメモリの 2 倍になります)。ただし、送信者が送信したのとまったく同じサイズのチャンクで受信者がデータを受信するという保証はありません (送信後)。 all, when you call send()/write(), それは実際にパケットが送信されたことを意味するものではありません. また, おそらくMTUが原因でパケットが分割されている可能性があります.

また、各読み取りのバイト数が大きく異なるのはなぜですか (一定である必要はありません)。

なぜこれが起こっているのかについてデバッグしたいかもしれません。使用中の NIC、その設定、そのドライバー、TCP/IP、TCP、イーサネット ネットワーク層の設定、送信側と受信側の間のもの (つまりスイッチ) など、何百もの要因があります。アプリケーションは前のチャンクを処理しています。NIC からユーザー空間アプリケーションへのデータの受け渡しが比較的非常に高価であるという事実を考えると、データがバッファーに入れられ、さまざまなサイズで取得されることは驚くべきことではありません。

1 回の読み取りで 256KB を確実に受信する方法はありますか?

あるかもしれません。ブロッキングread()を使用して、少なくとも 256KB を受信した場合、またはエラーが発生した場合にのみ、OS がプロセスをウェイクアップするように要求する場合があります。

于 2012-11-24T17:30:37.253 に答える
2

送信するデータのパケットは約 180 個ありますが、これは大量のデータにはほど遠いものです。Nagleは、送信中および受信中に任意の量のパケットを OS によってバッファリングさせます。

バッファリングされたパケットがいつ提示されるかのトリガーはrecv()、実装次第です。一定の時間が経過した後、または一定量の内部バッファ サイズに達した後、すべてのパケットが表示される可能性があります。SO_RCVLOWAT一部の OS では、ソケット オプションを使用してこれらのレベルを変更できます。

于 2012-11-24T17:30:44.823 に答える