buffer i/o using read(2) on BSD sockets

John F Nixon jnixon at andrew.ATL.GE.COM
Thu Mar 8 00:52:35 AEST 1990


ables at lot.ACA.MCC.COM (King Ables) writes:
> I've been using read(2) to read data from a socket and am having
> problems when the buffers get large...  I want to read an arbitrarily large 
> block of data and not have to worry about message boundaries (hence 
> read/write rather than send/recv).

Sorry, but if you are using AF_INET SOCK_STREAM sockets, and it sounds like
you are from your problem description, read/write will not preserve record
boundaries.  From "Introductory 4.3BSD IPC"

    ... Stream communication implies serveral things.  ... as in pipes,
    no record boundaries are kept.  Reading from a stream may result in
    reading the data send from one or several calls to write() or only
    part of the data from a single call, if there was not enough room for
    the entire message, or if not all data from a large message has been
    transfered.

So, if you want reliability, you have to manage record boundaries.  If you
want record boundaries, you use SOCK_DGRAM and give up reliability.  I have
not used any other types of sockets... yet.

>I decided to try doing reads like I've seen in some source code, one character
>at a time.  When I changed my code to do (approximately) this:
>	while (read(hd, &c, 1) == 1) buf[count++] = c;
>Then it gets all 8000 characters!

This tells me that you are seeing problems due to the lack of record boundaries
(or stating it another way, not all of your write arrives in one read).

You don't have to do it character at a time!  You do have to include a 
record size to keep yourself straight.  Once you know the record size, you
can ask for all of the data, accept what you get, and ask for the rest.
Repeat till everything is there.

    while ( recordsize > sizehere ) {
        bytes = read (soc, buf + sizehere, recordsize - sizehere);

	/* error handling, make sure bytes is +ve */
        sizehere += bytes;
    }

The above fragment is more or less it.  You can do all error handling
in one place by making the read call a call to your own routine which then
calls read.  You can worry about blocking.  But at least you will get
all of your data.

--
----
jnixon at atl.ge.com                    ...steinmetz!atl.decnet!jnxion



More information about the Comp.unix.wizards mailing list