tags:

views:

50

answers:

2

Hi,

I'm downloading 6kB of data from a test instrument connected via TCP socket. I'm using SOCK_STREAM:

if((MySocket=socket(PF_INET,SOCK_STREAM,0))==-1) exit(1);

I haven't set the any buffer sizes, so I assume I'm using whatever the default is. I'm having a problem with receiving data. Here's the statement:

  if((recv(MySocket, &YRaw[indx], sizeChunk*2, 0))==-1)
     {perror("recv()"); exit(9); }  // where sizeChunk=3000; sizeof(YRaw[0])=2

where YRaw is a 3000 object array, each object is 2 bytes.

The problem I observe after running the code, is that about 3/4 of the way through YRaw array, there's a string of zeros, which are what I initialized the array to. It appears the receive function works fine up to 3/4 of the array, then skips a chunk of YRaw array (leaving the initialized values), then picks up again, and the YRaw array fills up. There's data remaining in the buffer to read, equal to the number of values skipped in the YRaw array.

I suspect this is related to some buffer in the system. Can anyone shed some light on how to fix this?

I don't know if it's related, but I also set TCP_NODELAY, shown here:

// TCP_NODELAY option minimizes latency by instructing system to send small msgs immediately
// Insert setsockopt() before connect() occurs
int StateNODELAY = 1; // turn NODELAY on
if(setsockopt(MySocket, IPPROTO_TCP,TCP_NODELAY,
   (void *) &StateNODELAY, sizeof StateNODELAY)==-1) {perror("setsockopt()"); exit(2); };

Best regards, gkk

+3  A: 

recv() doesn't necessarily fill the whole buffer. It just reads whatever is available and returns how many bytes have been read.

So inspect the return value to see how much data was available, process that data, and call recv() again until you received all the data you expect.

sth
You can also use the WAITALL flag to block until all requested data have been read or an error occurs.
Venza
Could you describe how to use WAITALL. That sounds promising... what #include <___.h> file do I need? What does an example line of code look like?
ggkmath
On Linux, MSG_WAITALL is an optional flag, given as 4th argument (i.e. instead of the 0 in your recv() call.
Andre Holzner
@ggkmath: Just loop around, calling `recv()` with the number of bytes still-to-read, until you get the total size you're after.
caf
A: 

You should definitively store the result of recv (i.e. not only check whether it's -1 or not). That's the size of bytes actually read and you need this to know how many bytes are valid in your buffer.

Apart from that, you should check if you can read more bytes without blocking and read more until it would block.

Buffer size limitations can be anywhere in the system, e.g. the Ethernet MTU or even on your sending device.

Andre Holzner
THanks, OK I modified the program, and I can see that as shown above it reads 4342 bytes out of the requested 6000 bytes. Does this mean that the sending device hadn't sent more than 4342 bytes before the recv function completed?I'm not sure what you mean by "block or "blocking" here. I'm using a similar program in Matlab and it's working fine (same machines/equipment).
ggkmath
Also, If I break the read up into 5 reads of 1200 bytes each, the first 3 recv's return the expected 1200 bytes, the fourth recv reads 742 bytes, and the last recv reads 1200 bytes. Does this help explain how to fix it?
ggkmath
Hmm, why would the fourth recv() return less than the expected 1200 bytes, if the fifth recv() returns the full 1200B? Wouldn't the fourth recv() wait until the ... Aaahaa!!! From what sth says above, the recv() command doesn't necessarily fill the whole buffer. Thus, the test instrument probably is streaming the data and the fourth read simply read everything available then returned. By the time the fifth recv() came around there was more data available to read. Makes sense, but then I suppose WAITALL is the answer then(?).
ggkmath
I you know exactly how many bytes to expect, you could use MSG_WAITALL (Linux) which blocks (i.e. does not return) until you have read the expected number of bytes (definitively worth a try) OR an error happens OR the TCP connection is closed.
Andre Holzner
Yes, I know exactly what to expect, and I'm using a Mac, which should be similar to Linux. Thanks so much!!!
ggkmath