Path: utzoo!utgpu!jarvis.csri.toronto.edu!cs.utexas.edu!usc!zaphod.mps.ohio-state.edu!rpi!crdgw1!ge-dab!puma!andrew.ATL.GE.COM!jnixon From: jnixon@andrew.ATL.GE.COM (John F Nixon) Newsgroups: comp.unix.wizards Subject: Re: buffer i/o using read(2) on BSD sockets Message-ID: <218@puma.ge.com> Date: 7 Mar 90 14:52:35 GMT References: <637@lot.ACA.MCC.COM> Sender: news@puma.ge.com Lines: 49 ables@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@atl.ge.com ...steinmetz!atl.decnet!jnxion