4

TCP トランスポート スタックの根底にあるのは、作成者によって時々文書化されている多数のバッファ制限です。WinXP SP3 で、これらのいずれかに遭遇したと思いますが、その理由がわかりません。

サーバーからデータを取得するための単純なクライアントを実装しました (同僚が Java で作成しました)。プロトコルは、データの長さ (ネットワーク順) を 4 バイトで書き込み、次にデータを書き込みます。サーバーは、データを 1024 バイト ブロックで TCP ストリームに書き込みます。クライアントはデータ バッファーの長さを正しく受け取り、メモリを割り当て、ループ内で recv を繰り返し呼び出して、すべてのデータを取得します。

unsigned int TCP_BlockSize = 4096;
unsigned int len;
int result;

...code to request len...
unsigned char *buf = new unsigned char[len];

if( len > TCP_BlockSize)
{
Uint32 currentLen = 0;
result = 0;
Uint32 failCount = 0;
while( currentLen < len && result >= 0)
{
        result = recv( sock, buf + currentLen, TCP_BlockSize );
        if( result > 0 )
    {
        currentLen = currentLen + result;
    }
    else
        {
    break;
        }
}
}

TCP_BlockSize を 4095 以下に設定すると、すべて問題なく、数メガバイトの転送を受信できます。4096 サイズの受信ブロックを試すと、残りのデータに対する最後の要求 (len - currentLen < TCP_BlockSize) は常に失敗し、戻り値 -1 と errno = 0 になります。データが送信され、815054 ~ 834246 バイトの間のどこかですべてが 4096 バイトの受信ブロックでブームになります。

もう 1 つの詳細: サーバーは、最後のバイトを送信した後にソケットを閉じます。なぜ残りのデータが返されないのでしょうか? ストリームが空ではなく閉じられていないときに recv から -1 を受け取るのは曖昧なので、ストリームが空閉じられるまで recv から -1 を返さないのは欠陥のように感じます。

では、最後のデータを取得するにはどうすればよいでしょうか。

4

1 に答える 1

2

次のようなものを試してください...

to_rcv = (len - currentlen < TCP_BlockSize) ? len - currentlen : TCP_BlockSize;
result = recv( sock, buf + currentLen, to_rcv);

そうすれば、最終的な recv は必要な量だけを要求し、それ以外の場合は TCP_BlockSize を要求します。

于 2009-01-14T01:15:18.640 に答える