doug@ws5.cis.temple.edu (Doug Bagley) (03/15/88)
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@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); } }
sarima@gryphon.CTS.COM (Stan Friesen) (03/21/88)
In article <12404@brl-adm.ARPA> doug@ws5.cis.temple.edu (Doug Bagley) writes: >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). I think you may have a sligght misunderstanding of what a select() on a write fd means. It means block until there is enough system buffer space to successfully complete a write on the fd. Since it is almost always true that there is sufficient buffer space for a write to succeed a select() on a writefds will almost always return immediately with the writefds altered. I suspect what you want is to wait until the consumer has read what you last wrote. This is rather difficult to do, and I will not go into it here. SIGH, select() may well be the BSD feature that I miss the most on System V UNIX. Does Sys 5 release 3 have it or its equivalent?
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/21/88)
In article <2958@gryphon.CTS.COM> sarima@gryphon.CTS.COM (Stan Friesen) writes: >SIGH, select() may well be the BSD feature that I miss the most >on System V UNIX. Does Sys 5 release 3 have it or its equivalent? Yes, it's called poll() and it only works on STREAMS. AT&T is however converting the whole character I/O system over to STREAMS and may have already done so by now. There is also a SIGPOLL signal available.
sarima@gryphon.CTS.COM (Stan Friesen) (03/28/88)
In article <7513@brl-smoke.ARPA> gwyn@brl.arpa (Doug Gwyn (VLD/VMB) <gwyn>) writes: > >Yes, it's called poll() and it only works on STREAMS. AT&T is however >converting the whole character I/O system over to STREAMS and may have >already done so by now. > >There is also a SIGPOLL signal available. Good, its about time. But... are PIPEs being converted to STREAMS? If not, then poll() is not fully equivalent to select().
gwyn@brl-smoke.ARPA (Doug Gwyn ) (03/28/88)
In article <3025@gryphon.CTS.COM> sarima@gryphon.CTS.COM (Stan Friesen) writes: >... are PIPEs being converted to STREAMS? As of Release 3.0, ordinary pipes were still ripped-off block-I/O inodes. Hidden away somewhere were "stream pipes", but you had to make a special effort to get them. I'm pretty sure that a forthcoming release will have the whole character I/O subsystem converted to STREAMS, but I don't know if AT&T plans to convert to (full-duplex) stream pipes. They certainly ought to; that is one of the most effective tools for user-mode juggling of streams.