2011-09-15 12 views
3

データのチャンクをCサーバに送信するJava TCPクライアントを作成しています。クライアント/サーバーは開発PC上で非常にうまく機能しました。このコードは、ハードウェアボードに展開するとパケット損失を示しました。私はログを持っているだけで、サーバーがすべてのパケットを受け取っていないことがわかっています。 テストするハードウェアがありません。したがって、最初のレベルでは、クライアントコードが必要なすべてのデータを送信していることを確認したいと思います。TCPクライアントとサーバ間でパケットロスが発生しないようにする

ここに私のコード(Javaのクライアント部分)です。これが確実に行われるようにするにはどうすればよいですか?タイミングなどのある再送コマンドがありますか?ここで

 Socket mySocket = new Socket("10.0.0.2",2800); 
     OutputStream os = mySocket.getOutputStream();   

     System.out.println(" Sending 8 byte Header Msg with length of following data to Server"); 
     os.write(hdr, 0, 8); 
     os.flush(); 

     System.out.println(" Sending Data "); 
     start = 0; 
     for(int index=0; index < ((rbuffer.length/chucksize)+1); index++){    
      if(start + chucksize > rbuffer.length) { 
       System.arraycopy(rbuffer, start, val, 0, rbuffer.length - start); 
      } else { 
       System.arraycopy(rbuffer, start, val, 0, chucksize); 
      } 
      start += chucksize ; 

      os.write(val,0,chucksize); 
      os.flush(); 
     } 

は、このデータを受け取り、Cの抜粋です:すべての

while ((bytes_received = recv(connected, rMsg, sizeof(rMsg),0)) > 0){ 

if (bytes_received > 0)  // zero indicates end of transmission */ 
    { 
    /* get length of message (2 bytes) */ 
    tmpVal = 0; 
    tmpVal |= rMsg[idx++]; 
    tmpVal = tmpVal << 8; 
    tmpVal |= rMsg[idx++]; 
    msg_len = tmpVal; 

    len = msg_len; 
    //printf("msg_len = %d\n", len); 
    printf("length of following message from header message : %d\n", len); 
    char echoBuffer[RCVBUFSIZE] ;   
    memset(echoBuffer, 0, RCVBUFSIZE); 
    int recvMsgsize = 0; 

    plain=(char *)malloc(len+1); 
    if (!plain) 
    { 
    fprintf(stderr, "Memory error!"); 
    } 
    for(i = RCVBUFSIZE; i < (len+RCVBUFSIZE); i=i+RCVBUFSIZE){ 
    if(i>=len){ 
     recvMsgSize = recv(connected, echoBuffer, (len - (i-RCVBUFSIZE)), 0); 
     memcpy(&plain[k], echoBuffer, recvMsgSize); 
     k = k+recvMsgSize; 
    } 
    else{ 
     recvMsgSize = recv(connected, echoBuffer, RCVBUFSIZE, 0); 
     memcpy(&plain[k], echoBuffer, recvMsgSize); 
     k = k+recvMsgSize; 
     } 
    } 
}//closing if 
}//closing while 
+0

あなたはパケットが失われた知ってどうすればよいですか? TCPは保証された配信プロトコルです。つまり、書き込みまたは読み取りのいずれかが失敗した場合、エラーが発生します。これはアプリケーションのエラーですか? –

+0

それは私を打つものです。 TCPは信頼できるプロトコルです。チャンクを受け取ったCサイドサーバのスニペットを投稿します。ハードウェアの問題でもあります。私はJavaのnoobであり、パケットを再送する方法があるかどうか確かめたいだけです。もちろん、プロトコルの信頼性のためにカーネルがこれをしているに違いありません。どう見ていますか? – user489152

+0

パケットはi/pレイヤーで廃棄されることがありますが、TCPはそれらを再送し、送信された順序で受信者に配信します。私はあなたのサーバーまたはクライアントのいくつかのバグを考える。 –

答えて

5

まずTCP/IPでのパケット損失のようなものはありません。このプロトコルは、正しい順序でバイトストリームを確実に送信するように設計されています。したがって、問題はアプリケーションまたは他の側で発生している必要があります。

私はこの全体のarraycopy()狂気(C誰を?)分析する気分では本当にないのですが、なぜあなただ​​けBufferedOutputStreamて一度に全体rbufferを送信していませんか?

、その後:

os.write(rbuffer); 

は私を信じて、BufferedOutputStreamは(チャンクにバイトを収集し、一度にそれらを送信する)まったく同じことをやっています。それとも、私は何かを逃していますか?

+0

@ user489152:forループ中にデータが変更されるのはなぜですか? – home

+0

データは変更されません。私は、ネットワークを詰まらせ、おそらくTCPウィンドウを超えている巨大なチャンクを受け取らなければならないのではないかと恐れて、バッファを設定しました。 – user489152

+0

@トーマス:入力いただきありがとうございます。私はBufferedOutputStreamを認識していませんでした。これを使うときにC側で特別な措置が取られなければならないのでしょうか? – user489152

0

私は次のようにC側のプログラムを変更し、それが動作するようになりました:

    printf("length of following message from header message : %d\n", len); 

        plain=(char *)malloc(len+1); 
        if (!plain) 
        { 
         fprintf(stderr, "Memory error!"); 

        } 
        memset(plain, 0, len+1); 
        int remain = len; 
        k= 0; 
        while (remain){ 
         int toGet = remain > RCVBUFSIZE ? RCVBUFSIZE : remain; 
         remain -= toGet; 
         int recvd = 0; 
         while(recvd < toGet) { 
          if((recvMsgSize = recv(connected, echoBuffer, toGet-recvd, 0)) < 0){ 
           printf("error receiving data\n"); 
          } 
          memcpy(&plain[k], echoBuffer, recvMsgSize); 
          k += recvMsgSize; 
          printf("Total data accumulated after recv input %d\n", k); 
          recvd += recvMsgSize; 
         } 
        } 
+1

なぜあなたは 'to'から' toGet'を引いていますか?あなたの 'recv'(何らかの理由で)が' toGet'バイトよりも小さいバイト数を読み込んだ場合、ストリームの終わりは無視されます。保存するには、代わりに 'recvMsgSize'を減算する必要があります。 –

+0

私のrecv関数はtoGet-recvdバイトを取得します。recvd + = recvMsgSize – user489152

+0

私はそれを見ていません。 –

関連する問題