Input/Output Multiplexing
Requests can be multiplexed among multiple sockets or multiple files.
Use select
()
to multiplex:
#include <sys/time.h> #include <sys/types.h> #include <sys/select.h> ... fd_set readmask, writemask, exceptmask; struct timeval timeout; ... select(nfds, &readmask, &writemask, &exceptmask, &timeout);
The first argument of select
()
is the number of file
descriptors in the lists pointed to by the next three arguments.
The second, third, and fourth arguments of
select
()
point to three sets of file descriptors: a
set of descriptors to read on, a set to write on, and a set on which
exception conditions are accepted. Out-of-band data is the only
exceptional condition. You can designate any of these pointers as a
properly cast null. Each set is a structure that contains an array of
long integer bit masks. Set the size of the array with
FD_SETSIZE
, which is defined in
select.h
. The array is long enough to hold one bit
for each FD_SETSIZE
file descriptor.
The macros FD_SET
(fd, &mask) and FD_CLR
(fd, &mask) add and delete, respectively, the file descriptor fd in the set mask
. The set should be zeroed
before use and the macro FD_ZERO
(&mask)
clears the set mask
.
The fifth argument of select
()
enables the specification of a timeout value.
If the timeout
pointer is NULL
,
select
()
blocks until a descriptor is selectable, or until a
signal is received. If the fields in timeout
are set to
0
, select
()
polls and returns immediately.
The select
()
routine returns the number of file descriptors that are
selected, or a zero if the timeout has expired. The select
()
routine returns -1
for an error or interrupt, with the
error number in errno and the file descriptor masks
unchanged. For a successful return, the three sets indicate which file descriptors
are ready to be read from, written to, or have exceptional conditions pending.
Test the status of a file descriptor in a select mask with the FD_ISSET
(fd, &mask) macro. The
macro returns a nonzero value if fd is in the set
mask
. Otherwise, the macro returns zero. Use
select
()
followed by a FD_ISSET
(fd, &mask) macro on
the read set to check for queued connect requests on a socket. For more information,
see the
select
(3C) man page.
The following example shows how to select on a listening socket for readability to determine
when a new connection can be picked up with a call to accept
(). The
program accepts connection requests, reads data, and disconnects on a single
socket.
Example 7-4 Using select
()
to Check for Pending Connections
#include <sys/types.h> #include <sys/socket.h> #include <sys/time/h> #include <netinet/in.h> #include <netdb.h> #include <stdio.h> #define TRUE 1 /* * This program uses select to check that someone is * trying to connect before calling accept. */ main() { int sock, length; struct sockaddr_in6 server; int msgsock; char buf[1024]; int rval; fd_set ready; struct timeval to; /* Open a socket and bind it as in previous examples. */ /* Start accepting connections. */ listen(sock, 5); do { FD_ZERO(&ready); FD_SET(sock, &ready); to.tv_sec = 5; to.tv_usec = 0; if (select(sock + 1, &ready, (fd_set *)0, (fd_set *)0, &to) == -1) { perror("select"); continue; } if (FD_ISSET(sock, &ready)) { msgsock = accept(sock, (struct sockaddr *)0, (int *)0); if (msgsock == -1) perror("accept"); else do { memset(buf, 0, sizeof buf); if ((rval = read(msgsock, buf, sizeof(buf))) == -1) perror("reading stream message"); else if (rval == 0) printf("Ending connection\n"); else printf("-->%s\n", buf); } while (rval > 0); close(msgsock); } else printf("Do something else\n"); } while (TRUE); exit(0); }
In previous versions of the select
()
routine, its arguments were pointers to
integers instead of pointers to fd_sets
. This style of call still
works if the number of file descriptors is smaller than the number of bits in an
integer.
The select
()
routine provides a synchronous multiplexing scheme. The
SIGIO
and SIGURG
signals, which is
described in Advanced Socket Topics,
provide asynchronous notification of output completion, input availability, and
exceptional conditions.