Help with select

Doug Bagley doug at ws5.cis.temple.edu
Wed Mar 16 01:11:11 AEST 1988


I am trying to learn how to use sockets in Ultrix 2.0 at a site with no
sources.  My problem is with the select function.  When I provide the
readfds and writefds parameters to the select function, only the writefds
parameter gets changed whether or not the process on the other end of the
socket is doing a read or a write.  Strangely enough, if I make the
writefds NULL or 0, and if the remote process is only writing to this
one, everything works fine -- the remote process' writes show up in the
readfds (telling the selecting process that it can read).

Could someone help me out by: correcting any misinterpretation on my
part, or by referring me to a good reference on BSD IPC in the Internet
domain, or perhaps sending me a sample of code that uses select to
multiplex reads and writes at the same time?

I have included a stripped down version of the offending program below.

Thanks in advance,
Doug Bagley
(CSNET: bagley at temple.edu)

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <netdb.h>
#include <errno.h>

main(argc, argv)
int	argc;
char	*argv[];
{
    struct	sockaddr_in	sin, from;
    int	i, s, s2, smax, smin, fromlen, mask, writefds[1], readfds[1], nfound;

    /* get the port number from command line arg */
    if (argc != 2) exit(1);
    s = socket(AF_INET, SOCK_STREAM, 0);
    if (s == -1) exit(1);
    sin.sin_family = AF_INET;
    sin.sin_port = htons(atoi(argv[1]));
    if (bind(s, (caddr_t)&sin, sizeof(sin)) < 0) exit(1);
    /* listen on specified port */
    listen(s, 5);
    smax = s+1; smin = smax;
    /* mask contains all currently known socket descriptors */
    mask = (1<<s);

    for (;;) {
	readfds[0] = mask;
	writefds[0] = mask;
	/* we currently block forever on select */
	nfound = select(smax, readfds, writefds, 0, 0);
	if (nfound  < 0)
	    perror("select");

	/* test s for new socket connection requests */
	if (readfds[0] & (1<<s)) {
	    s2 = accept(s, &from, &fromlen);
	    if (s2 < 0) {
		if (errno != EINTR)
		  perror("accept");
	    }
	    /* add new socket to mask */
	    mask = mask | (1<<s2);
	    if (s2+1 > smax)  smax = s2+1;
	}

	if (readfds[0] != (1<<s))
	  /* check each known socket to see if it wants to write to us. */
	  for (i=smin; i<=smax; i++)
	    if (readfds[0] & (1 << i) )
	      /* read from the socket and queue message */
	      if (enqueue_msg(i) == -1) {
		  /* peer has closed socket, so close our end of socket */
		  close(i);
		  /* and remove socket from mask */
		  mask = mask & ~(1<<i);
		  /* decrease smax if necessary */
		  if (i+1 == smax) smax--;
	      }

	if (writefds[0] != (1<<s))
	  /* check each known socket to see if it wants to read from us. */
	  for (i=smin; i<=smax; i++)
	    if (writefds[0] & (1 << i))
	      /* remove a message from queue and write it to socket */
	      dequeue_msg(i);

    }
}



More information about the Comp.unix.wizards mailing list