Problem with sockets--atomic read.

I'm having a problem performing a read() call and retrieving all of the data.

I'm using IRIX 5.3 on an SGI Indy.  Here is the situation:

I have a socket opened for TCP/IP communication.  My client
process performs a writev() call.  The writev() is passed an
iovec with 2 buffers in it.  The total size of the two
buffers is less than PIPE_BUF (aka: PIPE_MAX).  The writev()
call returns to me with a positive value which is equal to
the number of bytes I expect to write.  I believe PIPE_BUF
is 10240 bytes, and my writev() call is writing 3875 bytes
(well below PIPE_BUF).  My server process then performs a
select() call to check for data on the socket and follows
that with a read().  The select() call is only checking for
data on a single socket and is used so that I can timeout
the recv() without using signals.  Anyway, the select()
detects the data on the socket and then I perform a recv().  
However, I am only able to read about 1500 bytes of the
message.  If I place a sleep(1) call just prior to the
recv() I get the whole message (3875 bytes).  This would
leave me to believe that recv() is returning prior to all
the data arriving on the socket.  I would think that an
atomic write on a TCP/IP socket would gurantee that the
message is received atomically as well, but this does not
seem to be the case.  I am wondering if there is some limit
imposed on TCP/IP sockets that is less than PIPE_BUF than I
should be using or do I just need to put that recv() call in
a loop with an accumulator and just keep trying to read
until all the data arrives?

Thanks,
Barry M. Caceres
barryc@alumni.caltech.edu
barrycAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

jos010697Commented:
Yep, you ansered your own question in your last sentence (see
above). It's quite peculiar indeed -- the writev() call can
send data atimically, while there's no guarantee at all that
recv() _receives_ the data in one sweep. The atomiicity simply
means that no other interleaved writes are done to a socket;
it doesn't mean that the data is not chopped up in smaller
parts though. A simple loop could do the job for you:

for (; c= recv(sock, buf, size, 0); c >= 0; size-= c)
   if (!size)
      break;

if (c < 0)
   /* check errno here */

kind regards,

Jos aka jos@and.nl
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
System Programming

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.