如何要求套接字等待更多数据到来

Yin*_*Zhu 5 .net c# sockets r

我正在玩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 + ".");
            }
Run Code Online (Sandbox Code Playgroud)

原因是.NET代码运行速度太快,R端无法那么快地发送数据。因此,我插入 Thread.Sleep(500) 之后的接收行没有获取所有数据。如果我在那里等待一段时间,那么它就可以获得所有数据。但我不知道要多久。

我有一些基本的想法来处理这个问题,例如,不断使用 this.socket.Receive() 来获取数据,但是如果那里没有数据 .Receive 就会阻塞在那里。

我对套接字编程经验很少,所以我询问此类问题的最佳实践。谢谢!

use*_*902 1

根据文档

如果您使用面向连接的 Socket,则 Receive 方法将读取尽可能多的可用数据,最多可达缓冲区的大小。

因此,您永远无法保证获得接收呼叫中所需的所有数据。您需要检查 Receive 实际返回了多少字节,然后对剩余字节发出另一个接收调用。继续该循环,直到获得所需的所有字节。