views:

697

answers:

3

Hi;

I was reading an article on Vadym Stetsiak's blog about how to transfer variable length messages with async sockets (url: http://vadmyst.blogspot.com/2008/03/part-2-how-to-transfer-fixed-sized-data.html).

He says :

What to expect when multiple messages arrive at the server? While dealing with multiple messages one has to remember that receive operation can return arbitrary number of bytes being read from the net. Typically that size is from 0 to specified buffer length in the Receive or BeginReceive methods.

So, even if I tell BeginReceive to read 100 bytes, it may read less than that and returns??? I am developing a network-enabled software (TCP/IP), and I always receive the same exact number of bytes I asked for.

I don't even understand the logic : why would Receive completes asynchronously if it didn't get every byte I asked for ... just keep waiting.

Maybe it has something to do with IP vs TCP?

Thank you for your help.

+1  A: 

If a socket is operating in an asynchronous mode, then it will return whatever bytes it actually has at the time, up to the requested amount at most, but can be (and usually is) less than the requested amount on any given read. You are not guaranteed to get as many bytes as you request each time. You have to keep reading over and over until you eventually get all of the bytes you need, then cache whatever is left over so it can be processed at a later time when more bytes are available. That is exactly what Vadym's example code is doing. This type of reading is asynchronous in that it has the socket receive bytes in the background while you continue doing other things, and then it notifies you when more bytes are available.

What you are thinking of is what a socket does in a synchronous mode instead. It waits for all requested bytes to arrive before allowing your code to continue with its work.

Remy Lebeau - TeamB
A: 

When an ethernet frame arrives, the ethernet device driver will copy the entire frame to its memory, only after copying the entire frame it will inform the upper layers(TCP). TCP layer then copies the data to its buffer and invokes the socket layer. The socket layer then copies the available data to its buffer space called socket buffers. finally the data is copied to the the users buffer and the process is signaled.

What are the scenarios in which the size of the data returned by receive() can be less than the requested data - 1) If the ethernet frame is less than the requested size 2) If the TCP buffer size(which is system wide size, can check for the sysctl parameter -net.ipv4.tcp_rmem in linux) is less than the requested size. 3) If socket buffer size(which is application specific size, can be set by setsockopt() using SO_RCVBUF) is less than the requested size.

Apart from the above scenarios, if the specified user buffer size is large enough to accomodate the complete frame, entire frame will be copied to the users buffer always.

IP layer does not have any role to play here.

Satish
A: 

Yes, this is a indeed a strange behavior. However, here's how I see it.. it may be wrong but that's the way I came to explain it to myself after some long hours of debugging session :-/

When you use Receive normally (synchronized), it reads n bytes than return.. fine. When you use BeginReceive (asynchronously), it calls you when it begins to read n bytes.

So, in other words, it really does try to read n bytes.. it just tell you when it begins to receive them instead of when it ends. And then, sometimes, it happens that reading n bytes is impossible but unfortunately, your begin signal has already been called.

I agree with you that the name is confounding.

good luck!