2011-11-10 58 views
4

我正在玩RserveCLI項目,這是一個.net客戶端與統計環境R通信。基本思想是發送數據/表示這個.NET客戶端和一個R會話通過TCP協議。如何讓套接字等待更多的數據來

其他人和我發現的一個錯誤是,超過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)之後的接收線路不會獲取所有數據。如果我在那裏等一段時間,那麼它可以獲得所有的數據。但我不知道多久。

我有一些基本想法來處理這個問題,例如,不斷使用this.socket.Receive()來獲取數據,但是如果沒有數據,那麼接收將會在那裏阻塞。

我在套接字編程方面經驗不多,所以我在問這種問題的最佳實踐。謝謝!

+1

此問題的典型解決方案是將數據累積到您自己的緩衝區中,並在每次接收後分析它以查看是否有消息要處理。請注意,您也可能需要處理兩個消息連續發送的情況。 –

回答

1

按照docs

如果您使用的是面向連接的插座,如可用,直到緩衝區的大小Receive方法將讀取儘可能多的數據。

因此,您永遠不會保證獲得接收呼叫中要求的所有數據。您需要檢查接收實際返回的字節數,然後針對其餘字節發出另一個接收調用。繼續循環,直到獲得所有要查找的字節。

1

根據定義,TCP是一種流媒體協議,而UDP是基於消息的。如果您嘗試接收的數據不包含整個消息的字節計數或某種消息結束指示符,則只需在socket.receive上循環,直到某個任意超時過期。此時,請檢查累計收到的數據是否完整。

相關問題