-1

C++ を使用してクライアント サーバー プログラムを開発したので、500kb 以上を受け取りたいのですが、クライアント メッセージが「!」で終了します 、だから私は最後のバイトまで受信したい(!) receive 、これは私のコードです。

do
  {
  int num = recv(*csock,  buf, bytesLeft,0);

if (num == 0)
{
  break;
}
else if (num < 0 && errno != EINTR)
{
  fprintf(stderr, "Exit %d\n", __LINE__);
  exit(1);
}
else if (num > 0)
{
  numRd += num;
  buf += num;
  bytesLeft -= num;
  fprintf(stderr, "read %d bytes - remaining = %d\n", num, bytesLeft);
}

  }

    while (bytesLeft != 0);
   fprintf(stderr, "read total of %d bytes\n", numRd);
4

3 に答える 3

6

質問の文言のためにあなたの問題が何であるか正確にはstrcatわかりませんが、ネットワーク経由で受信した生のバッファを追加するために使用することはできません。予期しないデータ転送が発生した場合でも、本当に「安全」です。c-string は NULL で終了すると想定されていますが、生のネットワーク バッファはそうではない可能性があり、strcatNULL で終了していない入力バッファを使用すると、オーバーランが発生します。それ以外のstrcat、データを受信するためにサイズ N バイトの既知の固定サイズのバッファーを使用し、バッファーの最後またはパケット送信の最後に到達するまで、バッファーを介して一時ポインターをインクリメントします。そうすれば、常に最大 N バイトまでネットワークから読み取ることができ、バッファ オーバーランの状況が発生するのを防ぐことができます。

たとえば、次のことができます (これは、すべてのコピーのため、最速またはより効率的なソリューションではありませんが、機能します)。

unsigned char buf[10000];  //10Kb fixed-size buffer
unsigned char buffer[MAXRECV];  //temporary buffer

unsigned char* temp_buf = buf;
unsigned char* end_buf = buf + sizeof(buf);

do
{       
    iByteCount = recv(GetSocketId(), buffer,MAXRECV,0);   

    if ( iByteCount > 0 )
    {
        //make sure we're not about to go over the end of the buffer
        if (!((temp_buf + iByteCount) <= end_buf))
            break;

        fprintf(stderr, "Bytes received: %d\n",iByteCount);
        memcpy(temp_buf, buffer, iByteCount);
        temp_buf += iByteCount;
    }
    else if ( iByteCount == 0 )
    {
        if(temp_buf != buf)
        {
            //do process with received data
        }
        else
        {
            fprintf(stderr, "receive failed");
            break;
        }
    }
    else
    {
        fprintf(stderr, "recv failed: ");
        break;
    }
} while(iByteCount > 0 && temp_ptr < end_buf);  //check for end of buffer
于 2012-04-04T12:33:45.700 に答える
1

1 つの連続したバイト バッファに 1MB 以上のデータがすべて必要ですか? もしそうなら、あなたは「!」で終わるプロトコルに固執します。長さを含むヘッダーがない場合、 memcpy() と realloc() がたくさん、または std::vector のような他のバッファタイプで立ち往生しています。これは実際には同じことを行います。

これらすべてのバイトを 1 つの文字列に格納する必要がない場合は、別の方法で格納できます。*buffer のベクトルなので、コピーは避けてください。

于 2012-04-04T12:47:12.970 に答える
1

ブロッキング ソケット (ソケットのデフォルト モード) を使用していると仮定すると、完全なバイト数が到着するのをrecv()待ってブロックされます。MAXRECVクライアントが送信するバイト数がそのバイト数よりも少ない場合、recv()は到着しないデータを待機してブロックします。

これを回避するには、次のいずれかを行う必要があります。

1) recv()1 バイトのバッファーで呼び出し、バイトrecv()に遭遇するまで呼び出し!ます。

2) 呼び出すselect()前に呼び出しrecv()て、ソケットに実際に読み取るデータがあることを検出し、次に呼び出して、ブロックせずioctlsocket(FIONREAD)に実際に読み取ることができるバイト数を決定し、そのバイト数を読み取った。recv()recv()

于 2012-04-05T00:02:03.620 に答える