Why does recv fail if the size of the requested buffer exceeds the amount of data available?

The TCP transport stream is based on a number of restrictions, sometimes documented by their authors. On WinXP SP3, I came across one of them, I think, and I can’t understand why.

I implemented a simple client for receiving data from a server (written by a colleague in Java). The protocol should record the data length (in network order) in four bytes, and then the data. The server writes data to the TCP stream in 1024 byte blocks. The client correctly obtains the length of the data buffer, allocates memory, and repeatedly calls recv in a loop to get all the data:

unsigned int TCP_BlockSize = 4096; unsigned int len; int result; ...code to request len... unsigned char *buf = new unsigned char[len]; if( len > TCP_BlockSize) { Uint32 currentLen = 0; result = 0; Uint32 failCount = 0; while( currentLen < len && result >= 0) { result = recv( sock, buf + currentLen, TCP_BlockSize ); if( result > 0 ) { currentLen = currentLen + result; } else { break; } } } 

If I set TCP_BlockSize to 4095 or lower, all is good and I can receive transfers with several megabytes. When I try to use 4096 receive blocks, the last request for the rest of the data, which is len-currentLen <TCP_BlockSize, always fails with a return value of -1, and errno = 0. I tried several experiments, such as cutting the size of the transmitted data and where- then between 815054 and 834246 bytes. Everything goes as an arrow for 4096 byte receive blocks.

Another detail: the server closes the socket after sending the last byte. What begs the question, why not return the rest of the data? It seems that the defect does not return -1 from recv until the stream becomes empty and closed, as it is ambiguous when the stream is not empty and closed to get -1 from recv.

So how can I get the latest data?

+4
source share
1 answer

Try something like ...

 to_rcv = (len - currentlen < TCP_BlockSize) ? len - currentlen : TCP_BlockSize; result = recv( sock, buf + currentLen, to_rcv); 

Thus, the last recv will only request the required amount, otherwise it will request TCP_BlockSize.

+2
source

All Articles