• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 438
  • Last Modified:

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
0
barryc
Asked:
barryc
1 Solution
 
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

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now