0

システム構成: Win XP (i7 2.1 Ghz) 外部 USB NIC。通信:マスタースレーブ通信。制約 - 通信プロトコル UDP。

ソケット構成: RecvFrom - ノンブロッキング。setsockopt を使用して、ソケット サイズが 1*1024*1024 に変更されました。

私のセットアップは、UDP を介してマスターと通信するノードで構成され、UDP フレームのペイロードで断片化されたデータを送信します。この断片化されたデータは、イーサネット フレームごとに 5 つの frament で構成されます。スレーブ ノードは、1270 バイトの断片化されたデータをマスターに送信します。スレーブは 2 ミリ秒未満で 18 ~ 20 フレームを送信します。

マスターは、このフレームをドロップせずに定期的に受信します。ただし、2 つの正しいフラグメントと残りの 3 つのフラグメントを含む UDP フレームからのランダムなペイロード データはガベージ値です。私は smae フラグメントにある Wireshark のトレースを観察しましたが、正しいデータを観察できますが、recvfrom API がこれら 3 つのフラグメントでガベージ データを収集する方法がいくつかあります。実際の情報がこのガベージ値に置き換えられているようです。この動作は、パケット数を 2 ミリ秒あたり 2 ~ 3 に減らすと低下します。

コンソールからトレースします。

_recvBuf[2]: 0x5b  _recvBuf[256}: 0x5c  _recvBuf[510]: 0x5d  
_recvBuf[764}: 0x5e  _recvBuf[1018}: 0x5f

_recvBuf[2]: 0x60  _recvBuf[256}: 0x61  _recvBuf[510]: 0x64  
_recvBuf[764}: 0x0  _recvBuf[1018}: 0x0

Expected and as in the Wireshark trace:
_recvBuf[510]: 0x64  --> should be _recvBuf[510]: 0x62
_recvBuf[764}: 0x0  --> should be _recvBuf[510]: 0x63
_recvBuf[1018}: 0x0  --> should be _recvBuf[510]: 0x64

ガベージ値は、ランダムなパケット番号に対して 0xcd に頻繁に繰り返されます。

!!! パケット 200 - エラー!!! パケット 20000 - エラー!!! パケット 60000 - エラー!!! パケット 2 - エラー

なぜこの動作なのか理解できません。

コード:

receive()
{
rc = select(_sock_fd+1, &read_fd, &write_fd, &excep_fd, &to);

    if (rc == 0 )  
    acess = 1; 

    else if (rc == SOCKET_ERROR) 
    {
        closesocket(_sock_fd);
        return -1;
    } 
    else 
    {
        if (!FD_ISSET(_sock_fd, &read_fd)) 
        {
            LogError("XCP: select() wrong socket descr");
            return -1;
        }
        else
        {

        rc = recvfrom(_sock_fd, (char *)_recvBuf, UDP_RECVBUFLEN, 0, (LPSOCKADDR)&_saddr, &cli_alen);

           printf("_recvBuf[3]: 0x%x  _recvBuf[2]: 0x%x  _recvBuf[256}: 0x%x  _recvBuf[510]: 0x%x  _recvBuf[764}: 0x%x  _recvBuf[1018}: 0x%x\n",_recvBuf[3],_recvBuf[2],_recvBuf[256],_recvBuf[510],_recvBuf[764],_recvBuf[1018]);
            _recvBuf[*(&rc)]='\0';

            if(rc == SOCKET_ERROR) 
            {
                closesocket(_sock_fd);
                return -1;
            }


                    _recvBufLen = rc;

            if (_recvBufLen > 0) 
            {
                int rc = 0;
                acess = 0;

                if (_rxNotification != NULL)
                    _rxNotification(_parent, _xhdl, _recvBuf, _recvBufLen);

                RxbufferLen=*(u16*)&_recvBufLen;

                /* Proto RX Queue Implementation Start */
                if(!(Fullqueue(Rxbufferqueue)))
                    Enqueue(Rxbufferqueue,_recvBuf);

                if(_recvBuf[4]==0xff)
                    acess = 1;
                else
                    acess = 0;

                return rc;
            }
            else 
                return 0;
        }
    }

関数に関する追加情報:

void XcpTransportUdp::Enqueue (Queuetype &queue, unsigned char buf[MAX_BUFFER_SIZE_QUEUE],u16 _recvBufLen)  // Push Function for Queue
{
    Rxbufferqueue.BackPointer=(Rxbufferqueue.BackPointer+1)%MAX_BUFFER_IN_QUEUE;
    Rxbufferqueue.Recv_length[Rxbufferqueue.BackPointer]=_recvBufLen;
    memcpy(Rxbufferqueue.Buffer[Rxbufferqueue.BackPointer],buf,Rxbufferqueue.Recv_length[Rxbufferqueue.BackPointer]);
}
u16 XcpTransportUdp::Dequeue (Queuetype &queue, unsigned char Output_buffer[MAX_BUFFER_SIZE_QUEUE])  // Pop Function for Queue
{
    Rxbufferqueue.Frontpointer =(Rxbufferqueue.Frontpointer+1)%MAX_BUFFER_IN_QUEUE;
    BufLen=Rxbufferqueue.Recv_length[Rxbufferqueue.Frontpointer];
    memcpy(Output_buffer,Rxbufferqueue.Buffer[Rxbufferqueue.Frontpointer],Rxbufferqueue.Recv_length[Rxbufferqueue.Frontpointer]);
    return BufLen;
}

:::Edir1::: エラーはソケットではなくメモリの初期化に関係していることがわかりました。enqueue 関数の memcpy 関数は、長さが 0cCD であるというエラーを報告します。この問題の解決策を知っている人はいますか..?

4

1 に答える 1

0

すぐに疑わしいことが 1 つあります。

特に戻りコードを配列へのインデックスとして使用する前に、失敗したFIRSTの戻りコードを確認する必要があります。設定しても安全だとは思いませんが、エラーが発生した場合に回線で発生するのはまさにそれです。また、単に使用できる場合のポイントは何ですか?_recvBuf[SOCKET_ERROR] = '\0';_recvBuf[*(&rc)] = '\0';*(&rc)rc

また、コードには の宣言が表示されていないため、文字 (サンプル コードには表示されない値を持つ別のシンボル)_recvBufを受け取るのに十分な大きさであると想定する必要があります。呼び出しでキャストする必要が本当にありましたか? 他の場所の文字配列であるかのように扱っているように見えるので、お願いします。また、それらのバイトを印刷する前に、必要な数のバイトを読み取ったことを確認しているかどうかもわかりません。UDP_RECVBUFLEN_recvBuf(char *)recv()

于 2013-03-14T13:57:47.680 に答える