How to ask a socket to wait for more data

I am playing with the RserveCLI project, which is a .net client that interacts with statistical environment R. The main idea is to send / commends data between this .NET client and the R session via TCP.

One error that I have discovered by others is that a large data port, say more than 10 thousand bytes, cannot successfully receive the transmission. I found, but in the following code snippet:

// 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 + "."); } 

The reason is that the .NET code is running too fast and the R side cannot send data quickly. So the receive line after my inserted Thread.Sleep (500) does not receive all the data. If I wait there for a while, then he can get all the data. But I do not know how long.

I have a basic idea to deal with the problem, for example, to constantly use this.socket.Receive () to receive data, but if there is no data, .Receive will be blocked there.

I have little experience in socket programming, so I am asking the best practice for this kind of problem. Thanks!

+4
source share
2 answers

According to docs :

If you use a connection-oriented Socket, the Receive method will read as much data as is available, up to the size of the buffer.

Thus, you never guarantee that all data requested when receiving a call is received. You need to check how many bytes were actually returned by the Recipient, and then issue another receive call for the remaining bytes. Continue this loop until you get all the bytes you were looking for.

+1
source

By definition, TCP is a streaming protocol, while UDP is message-based. If the data you are trying to get does not contain the number of bytes for the whole message or some kind of indicator of the end of the message, you just need to loop into socket.receive until a certain arbitrary timeout expires. At this point, check the collected data for completeness.

+1
source

Source: https://habr.com/ru/post/1380600/


All Articles