2011-11-10 55 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上循环,直到某个任意超时过期。此时,请检查累计收到的数据是否完整。

相关问题