2011-11-10 7 views
4

私はRserveCLIプロジェクト(これは統計環境Rと通信する.netクライアントです)で遊んでいます。基本的なアイデアはこの.NETクライアントとTCPプロトコルを介してRセッション。ソケットが多くのデータを待つようにする方法

他の人と私が気付いたバグは、大きなデータトランク、たとえば10kバイトを超えるものが転送を正常に行えないということです。私が見つかりましたが、次のコードスニペットに:

 // send the commend to R, then R will do some computation and get the data ready to send back 
     int toConsume = this.SubmitCommand(cmd, data); 
     var res = new List<object>(); 
     while (toConsume > 0) 
     { 
      var dhbuf = new byte[4]; 
      if (this.socket.Receive(dhbuf) != 4) 
      { 
       throw new WebException("Didn't receive a header."); 
      } 

      byte typ = dhbuf[0]; 

      // ReSharper disable RedundantCast 
      int dlength = dhbuf[1] + (((int)dhbuf[2]) << 8) + (((int)dhbuf[3]) << 16); 

      // ReSharper restore RedundantCast 
      var dvbuf = new byte[dlength]; 

      // BUG: I added this sleep line, without this line, bug occures 
      System.Threading.Thread.Sleep(500); 

      // this line cannot receive the whole data at once 
      var received = this.socket.Receive(dvbuf); 
      // so the exception throws 
      if (received != dvbuf.Length) 
      { 
       var tempR = this.socket.Receive(dvbuf); 
       throw new WebException("Expected " + dvbuf.Length + " bytes of data, but received " + received + "."); 
      } 

理由は、.NETコードがあまりにも速く実行され、R側はその高速なデータを送信することができないということです。したがって、私の挿入されたThread.Sleep(500)の後の受信ラインは、すべてのデータを取得しません。そこにある時間を待つと、すべてのデータを取得できます。しかし、私はどれくらいの時間がかかりません。

私はこの問題に対処するためにいくつかの基本的な考え方を持っています。たとえば、このソケットを使用してデータを取得するには、Receive()を使用します。

私はソケットプログラミングの経験が少ないので、この種の問題のベストプラクティスを尋ねています。ありがとう! docsによると

+1

この問題の典型的な解決方法は、受信するたびに独自のバッファにデータを蓄積して解析し、処理するメッセージがあるかどうかを確認することです。 2つのメッセージが連続して送信されるケースも処理する必要があることに注意してください。 –

答えて

1

:あなたは、接続指向のソケットを使用している場合は、バッファのサイズまで、利用できるよう

、受信方法は、できるだけ多くのデータを読み込みます。

受信コールで尋ねられたすべてのデータを取得することは決して甘やかされません。 Receiveによって実際に返されたバイト数を確認し、残りのバイトに対して別の受信呼び出しを発行する必要があります。あなたが探していたすべてのバイトを取得するまでループを続けます。

1

定義上、TCPはストリーミングプロトコルであり、UDPはメッセージベースです。受信しようとしているデータにメッセージ全体のバイト数やend-of-messageインジケータが含まれていない場合は、任意のタイムアウトが期限切れになるまでsocket.receiveをループするだけです。その時点で、蓄積された受信データをチェックして完全性を確認します。

関連する問題