我正在玩RserveCLI项目,这是一个与统计环境R通信的.net客户端。基本思想是通过TCP协议在此.NET客户端和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)后的接收行无法获取所有数据。如果我在那里等一段时间,那么它可以获得所有数据。但我不知道多久。
我有一些基本的想法来处理这个问题,例如,连续使用this.socket.Receive()来获取数据,但是如果没有数据,那么.Receive会阻塞那里。
我在套接字编程方面经验不足,所以我问这个问题的最佳实践。谢谢!
答案 0 :(得分:1)
根据docs:
如果您使用的是面向连接的套接字,则Receive方法将读取尽可能多的数据,最大可达缓冲区大小。
因此,您无需保证在接听电话中获取所有要求的数据。您需要检查Receive实际返回的字节数,然后为剩余字节发出另一个接收调用。继续循环,直到获得所需的所有字节。
答案 1 :(得分:1)
根据定义,TCP是流协议,而UDP是基于消息的。如果您尝试接收的数据不包含整个消息的字节数或某种消息结束指示符,则只需在socket.receive上循环,直到某个任意超时到期为止。此时,检查累积的接收数据是否完整。