Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Nov 1996 10:48:35 -0700 (MST)
From:      Terry Lambert <terry@lambert.org>
To:        jgreco@brasil.moneng.mei.com (Joe Greco)
Cc:        terry@lambert.org, jdp@polstra.com, scrappy@ki.net, jgreco@brasil.moneng.mei.com, hackers@FreeBSD.org
Subject:   Re: Sockets question...
Message-ID:  <199611151748.KAA26388@phaeton.artisoft.com>
In-Reply-To: <199611150414.WAA26986@brasil.moneng.mei.com> from "Joe Greco" at Nov 14, 96 10:14:34 pm

next in thread | previous in thread | raw e-mail | index | archive | help
> > > Well now, wait a minute.  As long as you haven't set the socket for
> > > non-blocking I/O, the write will always block until it's written the
> > > full N bytes that you asked for.  In other words, the write will always
> > > return either -1 or N.  Only if it's set up for non-blocking I/O can it
> > > return a short count.  Writes are different from reads in this respect.
> > 
> > The problem that is supposedly being addressed by looking at the bytes
> > written is knowing that the data will be available as a unit to the
> > reader.
> 
> Wrong, Terry.
> 
> The problem that is supposedly being addressed (and as the person who
> wrote the advice, I am telling you indisputably that this is what is
> being addressed) is that sometimes, people will forget that they are
> writing to a particular type of socket (such as {,non}blocking) and
> will inadvertently forget to check to see if all the data was written.

Non-blocking sockets for reliable stream protocols like TCP/IP are
a stupid idea.

If I wanted datagrams, I would pick a protocol like UDP.

> In the case of a nonblocking socket, the test is mandatory.

What is this, a bizzarre method of dealing with source quench on TCP?

What is the point of a non-blocking write if this is what happens?

I assume the only case where this is possible is where local buffer
space is not available to queue all the write data?

I assume you would use this for "frigging huge writes which you expect
to exceed the available buffer space"?  This is potentially useful
for lazy programmers, and for directed finite state automatons.  On
the other hand, I would expect that the initial write failure would set
the size of the expected delivery on the reliable stream, and that
subsequent writes would then pe packed off as "additional frags" up
to the satisfaction of the original (failed) write request.

Otherwise, you have just un-formatted your transport contents.  8-(.


> In the case of an indeterminate socket, the test is also mandatory -
> precisely BECAUSE you don't know.

Indeterminate sockets are evil.  They are on the order of not knowing
your lock state when entering into a function that's going to need
the lock held.


> > If you don't use non-blocking I/O, the read will block until the buffer
> > is full.  Use blocking I/O, and you won't have the problem with the
> > reader returning before it should (or shouldn't).  Otherwise the RPC
> > interfaces wouldn't work at all.
> 
> I am not too sure that statement is true...  but then I am a paranoid
> programmer, so I always define an xread() function guaranteed to do what
> I mean.  Still, that bothers me...  

It bothers me too... I am used to formatting my IPC data streams.  I
either use fixed length data units so that the receiver can post a
fixed size read, or I use a fix length data unit, and guarantee write
ordering by maintaining state. I do this in order to send a fixed
length header to indicate that I'm writing a variable length packet,
so the receiver can then issue a blocking read for the right size.


> > Instead of making a non-blocking read for which "it's OK if no data
> > is available", use select() and only call a blocking read if the select
> > is true.
> 
> And I think this is what I was looking for...
> 
> If you have a blocking read, select() returns true on a FD because one
> byte is available, and you try a read(1000), will it block?

Yes.  It will block pending all 1000 bytes being available.

> I am reasonably certain that it will not - it will return the one byte.
> 
> Ahhh.  Yes.
> 
> % man 2 read
> (SunOS version)
> 
>      Upon successful completion, read() and  readv()  return  the
>      number of bytes actually read and placed in the buffer.  The
> 
> Sun Release 4.1   Last change: 21 January 1990                  1
> 
> READ(2V)                  SYSTEM CALLS                   READ(2V)
> 
>      system guarantees to read the number of bytes  requested  if
>      the  descriptor references a normal file which has that many
>      bytes left before the EOF (end of file),  but  in  no  other
>      case.
> 
> Key words, "but in no other case"..

That isn't the same as "and guarantees to return random numbers in all
other cases".  8-).

The question, I suppose, is whether pending packet data less than the
packet length from the transmitter is fragged.

To answer that, I refer you to socket(2).

Specifically, you are describing the difference between SOCK_STREAM
and SOCK_SEQPACKET... the short reads you are defining are for the
SOCK_SEQPACKET case.  From the man page:

     The communications protocols used to implement a SOCK_STREAM insure that
     data is not lost or duplicated.  If a piece of data for which the peer
     protocol has buffer space cannot be successfully transmitted within a
     reasonable length of time, then the connection is considered broken and
     calls will indicate an error with -1 returns and with ETIMEDOUT as the
     specific code in the global variable errno. The protocols optionally keep
     sockets ``warm'' by forcing transmissions roughly every minute in the ab-
     sence of other activity.  An error is then indicated if no response can
     be elicited on an otherwise idle connection for a extended period (e.g. 5
     minutes).  A SIGPIPE signal is raised if a process sends on a broken
     stream; this causes naive processes, which do not handle the signal, to
     exit.


If you want to get technical, according to this description, if you are
using a SOCK_STREAM, then a read on a blocking socket will act like a
recv(2) or recvfrom(2) with flags MSG_WAITALL by default.


If you want the read to not hang pending arrival of all packets in
the run resulting from a single write...

Maybe you should be using send/recv instead of write/read?

Maybe you should be using SOCK_SEQPACKET instead of SOCK_STREAM?

IMO, it is not useful to use read(2) in conjunction with non-blocking
sockets.


I suggest you create a socket without setting any non-default options,
and then fcntl it with F_GETFL and look for the defaults for O_NONBLOCK
and O_ASYNC.  There is no substitute for asking the machine.  8-).


					Regards,
					Terry Lambert
					terry@lambert.org
---
Any opinions in this posting are my own and not those of my present
or previous employers.



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199611151748.KAA26388>