0

クライアントからのリクエストをtcpプロトコルで処理しているのですが、「send」機能を使用中にコンテンツの一部が欠落する現象を発見しました。コードは仲間です:

    _stprintf(cData,"[%s]",send_back);
    memset(send_back,0,sizeof(cData));
    int send_count;
    if((send_count=send(service_sock,cData,_tcslen(cData),0))!=SOCKET_ERROR){
        fwrite(cData,sizeof(char),_tcslen(cData),hFile);
        fflush(hFile);
        g_log->print_log("%c%c%c%c",cData[0],cData[1],cData[2],cData[send_count-1]);
        g_log->print_log("buffer len is :%d , send %d bytes",_tcslen(cData),send_count);
        fclose(hFile);
        memset(cData,0,sizeof(cData));
        return true;
    }

send 関数は常に成功し、_tcslen(cData) の値は send_count に等しく、cData[send_count-1] は ']' です。しかし、Wireshark (キャプチャ ツール) を使用してソケットから送信されたパケットをキャプチャすると、']' の文字を含む一部のコンテンツが常に欠落していることがわかりました。コンテンツは JSON プロトコルによってカプセル化されるため、「]」が重要です。毎回送信される合計サイズは 8900 バイトです。しかし、リクエスト項目を 1 回 (前は 100) から 50 に変更すると、何も漏れがなく、返送のサイズは約 4000 バイトです。なぜこれが起こったのかわかりません。

私のログ ファイルから、'cData' という名前の配列にすべてのコンテンツが含まれていることは確かですが、wireshark によってキャプチャされたパケットのコンテンツが完全ではないのはなぜですか?

4

1 に答える 1

0

TCP を使用しているのを見ると、既に間違っているように見えます。

まず、TCP はストリーム プロトコルであり、1 回限りのパケット (特に小さい) には適していませんが、代わりに UDP を使用するよりもはるかに大きな利点があります。TPC を制御できない場合は、要求が正しく処理されていることを確認することしかできないことに注意してください。実際の通信は Winsock ライブラリによって行われます。

送信関数の len パラメーターは必須ではないことを常に覚えておいてください。これは、バッファーの大きさと一度に送信できる量に関するヒントであり、送信したい量よりも少ない値を返す場合があり、これは多くの要因に依存する可能性があります。よくあることですが、ループバック デバイスを使用しているとしたら、おそらくこれを行うことは決してないでしょう。つまり、send は実際に要求したものを送信します。実際のネットワークでは、約 90% またはそれより低い確率で一度に送信する可能性があります。

つまり、戻り値を確認し、必要なだけ送信されていない場合は send を再度呼び出し、recv を使用して反対側で同じことを行い、受信するまで recv を呼び出します。必要なだけのデータ。この方法は、ネットワーク経由で送信するデータ量が正確にわかっている場合にのみ機能します。

データの損失については、TCP は、send の戻り値を確認したと仮定して、ほぼ常にデータを送信していると言えます。データの損失など、ネットワークに問題がある場合は、TCP 再送信パケットが表示されます。

データを送信する方法には、これがより適しています。これは、必要な量のデータを実際に送信することを確認するためです。

xint xsend(SOCKET s,const char* buf,xint len)
{
xint lastSize;
xint result;

    if (len==0 || s==(SOCKET)NULL || buf==(const char*)NULL)
        return SOCKET_ERROR;

    lastSize=0;
    result=0;

    do
    {
        result=send(s,buf+lastSize,len-lastSize,0);

        if (result==0)
            return 0;
        if (result==SOCKET_ERROR)
            return SOCKET_ERROR;
        if (result==len)
            return len;
        if (result>len)
        {
            xlog(1,"xsend : socket sent too much data [ %i of %i ]",result,len);
            return SOCKET_ERROR;
        }
        lastSize+=result;
        if (lastSize>len)
        {
            xlog(1,"xsend : socket sent too much data ( overall ) [ %i of %i ]",result,len);
            return SOCKET_ERROR;
        }
        if (lastSize==len)
            return len;
    }
    while (1);

    xlog(2,"failed to do xsend");
    return SOCKET_ERROR;
}

このコードは、私のプロジェクトの 1 つからの単なるコピー ペーストです。xlog は単純なログ機能です。理解できます。

于 2013-10-19T16:07:41.547 に答える