Thursday, 5 November 2015

Select() Call in Sockets

SELECT call is generally used  in server side (server socket ) to service the multiple clients asynchronously.  Most of the time it is been used in non blocking sockets.


select()  allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become "ready" for some class of I/O operation (e.g., input possible). A file descriptor is considered ready if it is possible to perform the corresponding I/O operation (e.g., read(2)) without blocking.


Four macros are provided to manipulate the sets.
  • FD_ZERO() clears a set.
  • FD_SET() and
  • FD_CLR() respectively add and remove a given file descriptor from a set.
  • FD_ISSET() tests to see if a file descriptor is part of the set;

select() call also be used to timeout for the function.

#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

int main(void) {
    fd_set rfds;
    struct timeval tv;
    int retval;

    /* Watch stdin (fd 0) to see when it has input. */
    FD_ZERO(&rfds);
    FD_SET(0, &rfds);
 

    /* Wait up to five seconds. */
    tv.tv_sec = 5;
    tv.tv_usec = 0;


    retval = select(1, &rfds, NULL, NULL, &tv);
 

   /* Don’t rely on the value of tv now! */
    if (retval == -1)
        perror("select()");
    else if (retval)
        printf("Data is available now.\n");
        /* FD_ISSET(0, &rfds) will be true. */
    else
        printf("No data within five seconds.\n");
    return 0;
}


Output:
If there is no input from user with in 5 secs, it will print as "No data within five seconds.\n"
If there is any input in 5 secs, it will print as "Data is available now\n"
Another Example:

#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>

int
input_timeout (int filedes, unsigned int seconds)
{
  fd_set set;
  struct timeval timeout;
  int ret;

  /* Initialize the file descriptor set. */
  FD_ZERO (&set);
  FD_SET (filedes, &set);

  /* Initialize the timeout data structure. */
  timeout.tv_sec = seconds;
  timeout.tv_usec = 0;

  /* select returns 0 if timeout, 1 if input available, -1 if error. */
  ret =  (select (FD_SETSIZE,  &set, NULL, NULL,  &timeout));

  return ret;
}

int
main (void)
{
  fprintf (stderr, "select returned %d.\n",
           input_timeout (STDIN_FILENO, 5));
  return 0;
}