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