[comp.unix.wizards] Non-blocking accept

brian@radio.UUCP (09/02/87)

The following is probably very simple, but darned if I can find it in the 
manuals :-(

I am writing a graphics "server" on our Sun (3/180, SunOs 3.4=BSD 4.2), which
I am implementing through socket i/o. When the server is not connected I would
like to poll accept(2) periodically looking for new connections. It should be
non-blocking so that it doesn't adversely affect screen activity.

So my question is - how do I make accept non-blocking? I know it can be done.
I'm quite happy with read/write being blocking, although if they must also be
non-blocking that probably wouldn't be a hardship, although my preference
would be to leave them blocking. If it matters I'm writing the application
under the SunView windowing system.

Thanks.

-- 
Brian Glendenning         UUCP   - {allegra,decvax,pyramid}!utgpu!radio!brian 
+1 (416) 978-5558         BITNET - glendenn@utorphys.bitnet

chris@mimsy.UUCP (Chris Torek) (09/04/87)

In article <479@radio.toronto.edu> brian@radio.toronto.edu (Brian
Glendenning) writes:
>I am writing a graphics "server" on our Sun (3/180, SunOs 3.4=BSD 4.2), which
>I am implementing through socket i/o. When the server is not connected I would
>like to poll accept(2) periodically looking for new connections. It should be
>non-blocking so that it doesn't adversely affect screen activity.
>
>So my question is - how do I make accept non-blocking? I know it can be done.

Instead of making accept nonblocking, perform it only when it will not
block.  To find out when the latter is true, select the service socket
(the one on which you have listen()ed) for reading:

	#include <sys/types.h>
	/* beware, 4.3BSD/V8 macros below */
	fd_set	rset, wset;
	...
		if (listen(serverfd, 5))
			error(...);
		FD_ZERO(&rset);
		FD_SET(serverfd, &rset);
		highfd = serverfd;
		for (;;) {
			fd_set r = rset, w = wset;
			int newfd, sourcesize;
			struct sockaddr_in source;

			nsel = select(highfd, &r, &w, (fd_set *)0,
				(struct timeval *)0);
			if (nsel <= 0) {
				/* if (errno == EINTR) continue; (optional) */
				error(...);
			}
			if (FD_ISSET(serverfd, &r)) {
				sourcesize = sizeof(source);
				newfd = accept(servfd, &source, &sourcesize);
				if (newfd < 0)
					error(...);
				FD_SET(newfd, &rset);
				FD_SET(newfd, &wset);
			}
			...
		}
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7690)
Domain:	chris@mimsy.umd.edu	Path:	seismo!mimsy!chris

nawaf@muffy.CalComp.COM (Nawaf K. Bitar) (09/04/87)

In article <8395@mimsy.UUCP>, chris@mimsy.UUCP (Chris Torek) writes:
> In article <479@radio.toronto.edu> brian@radio.toronto.edu (Brian
> Glendenning) writes:
> >like to poll accept(2) periodically looking for new connections. It should be
> >non-blocking so that it doesn't adversely affect screen activity.
> >
> >So my question is - how do I make accept non-blocking? I know it can be done.
> 
> Instead of making accept nonblocking, perform it only when it will not
> block.  To find out when the latter is true, select the service socket
> (the one on which you have listen()ed) for reading:
> 
>				.
>				.
> 			nsel = select(highfd, &r, &w, (fd_set *)0,
> 				(struct timeval *)0);
>				.
>				.
> 			if (FD_ISSET(serverfd, &r)) {
> 				sourcesize = sizeof(source);
> 				newfd = accept(servfd, &source, &sourcesize);
> 				if (newfd < 0)
> 					error(...);
> 				FD_SET(newfd, &rset);
> 				FD_SET(newfd, &wset);
> 			}



In essence what has happened here is that the select() above blocks
indefinitely until some input is available.  If I understand the
original request you would rather poll once in a while and not
block at all.  I can think of three possibilities:

	i)   Use the select() as above but supply a
	     pointer to a zero-valued timeval struct
	     and thus affect a poll

	ii)  Set up the socket so that it is non-blocking;
	     this will cause accept() to return an
	     EWOULDBLOCK if no data is pending

	iii) The advanced topics section of the IPC primer
	     blurbs something about using SIGIO with
	     asynchronous I/O.  It seems to suggest delivery
	     of the signal on input availabilty - this might be
	     worth investigating further.

I hope this helps.


-- 
Nawaf Bitar
uucp:	 ...{harvard,decvax}!elrond!nawaf or nawaf@elrond.CalComp.COM
usps:    CalComp (A Lockheed Company), Display Products Division,
	 Mail Stop PTP2-2D01, CS 908, Hudson NH 03051 (603) 885 8135

schung@cory.Berkeley.EDU (Stephen the Greatest) (09/04/87)

Strange..... The problem with me is that I want an accept(2) call to *block*
which it doesn't.  I want it to block itself when no connection is available
and timeout after a while.  I also want connect(2) to block and timeout.  Does
anyone know how to do that?


- Stephen

lubich@ethz.UUCP (09/06/87)

Use ioctl (sockd, FIONBIO, 1);
It works on my uVaxII and on a Vax785 both running Ultrix 32m
	--Hannes
-- 
~ UUCP/Usenet   :   {known world}!seismo!mcvax!cernvax!ethz!lubich
~ CSNET         :   lubich%ifi.ethz.chunet@relay.cs.net
~ ARPA          :   lubich%ifi.ethz.chunet@csnet-relay.arpa                
The usual disclaimer : No, it wasn't me, somebody must have used my account.

ron@topaz.rutgers.edu (Ron Natalie) (09/06/87)

Use select to poll the socket file descriptor after doing the listen.
A connection to be opened shows up as a "read" condition.  This is
how inetFC