select: Monitor read, write, and exception status

The select socket function monitors a list of file descriptors for readability, readiness for writing, and exception pending conditions. The list can contain nonsocket file descriptors, socket descriptors, or a combination of both.

Last updated

Changed for PUT00.

Format

#include  <sys/socket.h>
int       select(int *s,
                 short int noreads,
                 short int nowrites,
                 short int noexcepts,
                 long  int timeout);
s
Pointer to an array containing a list of file descriptors to check for readability, followed by a list of file descriptors to check for readiness for writing, followed by a list of file descriptors to check for exception pending conditions. The array can contain nonsocket file descriptors, socket descriptors, or a combination of both.
noreads
Number of file descriptors to be checked for readability.
nowrites
Number of file descriptors to be checked for readiness for writing.
noexcepts
Number of file descriptors to be checked for exception pending conditions.
timeout
Maximum interval, in milliseconds, to wait for the selection to be completed.

If the timeout value is 0, select does not wait before returning to the caller. If the timeout value is -1, select does not time out, but it returns when a file descriptor becomes ready. If the timeout value is a number of milliseconds, select waits for the specified interval before returning to the caller.

Normal return

The total number of ready file descriptors. A value of 0 indicates an expired time limit. If the return value is greater than 0, the file descriptors in the s argument that were not ready are set to -1.

Error return

A value of -1.

If an error occurs while monitoring a socket descriptor, errno and sock_errno are set to one of the following error codes.
E1052STATE
The socket was closed because the system was in or cycling down to 1052 state.
SOCFAULT
A timeout value was specified that is not valid.
SOCNETUNREACH
An ICMP message was received on this socket (in response to sent data) indicating that the destination IP address and/or destination port are not reachable.
SOCNOTSOCK
One of the sockets descriptors specified in the file descriptor array is not valid.
If an error occurs while monitoring a nonsocket file descriptor, errno is set to the following:
EBADF
One or more of the file descriptor sets specified a file descriptor that is not a valid open file descriptor or a file descriptor that is not supported through the select function.

Programming considerations

  • The select function monitors activity on a set of various file descriptors to verify if any of the file descriptors are ready for reading or writing, or if any exceptional conditions are pending. If the time limit expires, select returns to the caller.
  • If any file descriptors specified in the s argument represent sockets, you must issue a bind function on all the file descriptors you are monitoring that are sockets before issuing the select function.
  • The send low-water mark determines the minimum amount of data that must be available in the send buffer to allow the select for a write function to be processed. The send low-water mark is set by the SO_SNDLOWAT socket option of the setsockopt function.
  • The sum of the numbers specified for the noreads, nowrites, and noexcepts arguments cannot exceed the number of file descriptors specified in the s argument.
  • The select function takes a single array of file descriptors as input. If your application uses the BSD select model instead, use the tpf_select_bsd function rather than the select function.

Examples

The following example monitors a FIFO special file (or named pipe) and a socket for incoming messages.
#define MSG_BUFF 4096
#define TIMERINT 30
#define MAX_SELECT_FD 20
#define SELECT_TIMEOUT 2*1000

#include <sys/socket.h>
#include <signal.h>
#include <stdio.h>
#include <fcntl.h>

void SigAlrmH(int SIG_TYPE)    /* Handle alarm */

{
  char incoming_data[MSG_BUFF + 1];
  int bytes_in, i;

  int fd_fifo;                /* mkfifo file descriptor */
  char fifopath[] = "/tmp/my_fifo";

  int sd_inet;                /* socket descriptor */
  int slen;
  struct sockaddr_in sin, sockinet;

  int select_array[MAX_SELECT_FD];
  int nfds, Rfd, Wfd, Xfd;

  signal(SIGALRM, SigAlrmH);
  alarm(TIMERINT);

  /* Open the named pipe. */
  if ((mkfifo(fifopath, 777)) < 0)
     /* Handle the mkfifo error. */

  if ((fd_fifo = open(fifopath, O_RDONLY, 0)) < 0)
     /* Handle the open error. */

  /* Open the socket. */
  if ((sd_inet = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
     /* Handle socket error. */
  /* Set sockaddr parameters. */
  if ((bind(sd_inet, (struct sockaddr *)&sin, sizeof(sin))) < 0)
     /* Handle bind error. */

  for (;;) {
    /* Initialize select Parameters */
    select_array[0] = fd_fifo;
    select_array[1] = sd_inet;
    Rfd = 2;
    Wfd = 0;
    Xfd = 0;

    /* Enable signal interrupts to accept any timeout alarm.  */
    tpf_process_signals();

    /* Wait for incoming data, select timeout, or external alarm. */
    nfds = select(select_array, Rfd, Wfd, Xfd, SELECT_TIMEOUT);
    if (nfds == 0)    /* Process the select timeout condition. */
    if (nfds < 0)  /* Process the error condition. */

    /* Process the readable file or socket descriptors */
    for (i=0; i<nfds; i++) {
      if (select_array[i] == fd_fifo ) {
        bytes_in = read(fd_fifo, incoming_data, MSG_BUFF);
        /* Process the data from the named pipe. */
      }
      if (select_array[i] == sd_inet) {
        slen = sizeof sockinet;
        bytes_in = recvfrom(sd_inet, incoming_data, MSG_BUFF, 0,
                     (struct sockaddr *) &sockinet, &slen);
        /* Process the socket data. */
      }
    }  /* end for loop */
  }    /* end for loop */
}

Related information

See Programming support for z/TPF file system support for more information about nonsocket file descriptors. See z/TPF Transmission Control Protocol/Internet Protocol for more information about socket file descriptors.