|
|
C Interface
#include <time.h>
int select (nfds, readfds, writefds, exceptfds,timeout)
int nfds, *readfds, *writefds, *exceptfds;
struc timeval *timeout;
Description
The select intrinsic examines the file descriptors specified by the
bit masks readfds, writefds, and
exceptfds. The bits from 0 through nfds-1 are
examined. File descriptor f is represented by the bit 1 <
f in the masks. More formally, a file descriptor is
represented by the following:
fds[(f / BITS_PER_INT)] & (1 << (f % BITS_PER_INT))
When select completes successfully, it returns the three bit masks
modified as follows: For each file descriptor less than nfds,
the corresponding bit in each mask is set if the bit was set upon entry and
the file descriptor is ready for reading or writing, or has an exceptional
condition pending.
If timeout is a non-zero pointer, it specifies a maximum
interval to wait for the selection to complete. If timeout is
a zero pointer, the select waits until an event causes one of the
masks to be returned with a valid (non-zero) value. To poll, the
timeout argument should be non-zero, pointing to a zero valued
timeval structure. Specific implementations may place
limitations on the maximum timeout interval supported.
Any or all of readfds, writefds, and
exceptfds may be given as 0 if no descriptors are of interest.
If all of the masks are given as 0 and timeout is not a zero
pointer, select blocks for the time specified, or until interrupted
by a signal. If all of the masks are given as 0 and timeout is
a zero pointer, select blocks until interrupted by a signal.
Ordinary files always select true whenever selecting on reads, writes, and/or
exceptions.
Examples
Example 1
The following call to select checks if any of four sockets are ready
for reading. The select intrinsic times out after 5 seconds if no
sockets are ready for reading:
 |
NOTE: The code for opening the sockets or reading from the sockets is
not shown in this example and this example must be modified if the calling
process has more than 32 file descriptors open.
|
#define MASK(f) (1 << (f))
#define NSDS 4int sd[NSDS];
int sdmask[NSDS];
int readmask = 0;
int readfds;
int nfound, i;
struct timeval timeout;
/* First open each socket for reading and put the */
/* file descriptors into array sd[NSDS]. The code */
/* for opening the sockets is not shown here. */
for (i=0; i < NSDS; i++) {
sdmask[i] = MASK(sd[i]);
readmask |= sdmask[i];
}
timeout.tv_sec = 5;
timeout.tv_usec = 0;
readfds = readmask;
/* select on NSDS+3 file descriptors if stdin, stdout */
/* and stderr are also open */
if ((nfound = select (NSDS+3, &readfds, 0, 0, &timeout)) == -1)
perror ("select failed");
else
if (nfound == 0)
printf ("select timed out \n");
else
for (i=0; i < NSDS; i++)
if (sdmask[i] & readfds)
/* Read from sd[i]. The code for reading */
/* is not shown here. */
else
printf ("sd[%d] is not ready for reading \n",i);
Example 2
The following programming example shows how select can be used to
wait on multiple sockets.
/* This program is an example of how select can be
used on multiple sockets */
/* on MPE/iX. */
/* Compile with SOCKET_SOURCE and POSIX_SOURCE defined. */
/* Link with socketrl and libcinit. */
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/in.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <time.h>
#define TRUE 0
#define FALSE 1
main ()
{
int maxfds;
int sock, sock2, peer1;
int struc_len;
int fret;
int done = FALSE;
char data[256];
char data_to_send = 'D';
char *datptr;
int dlen;
int readfds;
int writefds;
struc timeval timeout;
struc sockaddr_in sockaddr;
sock = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP;
peer1 = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP);
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = INADDR_THISHOST;
sockaddr.sin_port = 4444;
struc_len = 8;
if (bind (sock, (struc sockaddr *) &sockaddr,
sizeof sockaddr) << 0 )
{
printf ("Bind failed\n");
};
listen (sock, 10);
sfcntl (peer1, F_SETFL, O_NONBLOCK);
/* connect() returns with EINPROGRESS. */
fret = connect (peer1, (struct sockaddr *) &sockaddr,
struc_len);
sock2 = accept (sock,
(struc sockaddr *) &sockaddr,
&struc_len);
/* Call recv to complete the connection */
recv (peer1, 0, 0, 0);
/* sock2 and peer1 are now connected */
daptr = data;
done = FALSE;
while (done == FALSE) {
/* This code example shows how to use select() to wait on
multiple sockets. Note that first you have to find the maximum
descriptor number being used. The appropriate bit(s) must be
set for the select masks and then they must be checked after
the call. */
/* In this example, sock2 is waiting to receive data from peer1.*/
if (peer1 << sock2) {
maxfds = sock2;
}
else
maxfds = peer1;
/* set a 5 second timer for the call to select(). */
timeout.tv_sec = 5;
timeout.tv_usec = 0;
writefds = (1 << peer1);
readfds = (1 << peer1) + (1 << sock2);
fret = select (maxfds + 1, &readfds, &writefds, 0,
&timeout);
if (fret << = 0) {
printf ("error1\n");
done = TRUE;
}
else
{
if ((readfds && (1 << sock2)) ! = 0) {
dlen = 100;
fret = recv (sock2, datptr, dlen, 0);
printf ("received %d bytes.\n", fret);
if (data[0]! = data_to_send) {
printf ("error2\n");
};
done = TRUE;
}
else
{
if ((writefds && (1 << peer1))! = 0) {
dlen = 1;
data[0] = data_to_send;
fret = send (peer1, datptr, dlen, 0);
printf ("sent %d bytes.\n", fret);
}
else
{
printf ("error3\n");
}
}
};/* end else */
};/* end while */
}
Return Value
The select intrinsic returns the number of descriptors contained in
the bit masks. If an error occurs, -1 is returned and an error code is stored
in errno. If the time limit expires, then select
returns 0, and all of the masks are cleared.
Errors
The select intrinsic returns the following errors:
Error Code |
Description |
[EBADF] |
One or more of the bit masks specified an invalid descriptor. |
[EFAULT] |
One or more of the pointers was invalid. |
[EINVAL] |
An invalid timeval was passed for timeout. |
[EINVAL] |
The value of nfds is less than zero. |
 |
NOTE: The file descriptor masks are always modified on return, even
if the call returns as the result of a timeout.
|
Author
The select intrinsic was developed by Hewlett-Packard and the
University of California, Berkeley.
|