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.