Taken from the original at http://www.ecst.csuchico.edu/~beej/guide/net/ ... see end of writeup for Copyright statement.

select()--Synchronous I/O Multiplexing

This function is somewhat strange, but it's very useful. Take the following situation: you are a server and you want to listen for incoming connections as well as keep reading from the connections you already have.

No problem, you say, just an accept() and a couple of recv()s. Not so fast, buster! What if you're blocking on an accept() call? How are you going to recv() data at the same time? "Use non-blocking sockets!" No way! You don't want to be a CPU hog. What, then?

select() gives you the power to monitor several sockets at the same time. It'll tell you which ones are ready for reading, which are ready for writing, and which sockets have raised exceptions, if you really want to know that.

Without any further ado, I'll offer the synopsis of select():

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

int select(int numfds, fd_set *readfds, fd_set *writefds,
           fd_set *exceptfds, struct timeval *timeout);

The function monitors "sets" of file descriptors; in particular readfds, writefds, and exceptfds. If you want to see if you can read from standard input and some socket descriptor, sockfd, just add the file descriptors 0 and sockfd to the set readfds. The parameter numfds should be set to the values of the highest file descriptor plus one. In this example, it should be set to sockfd+1, since it is assuredly higher than standard input (0).

When select() returns, readfds will be modified to reflect which of the file descriptors you selected is ready for reading. You can test them with the macro FD_ISSET(), below.

Before progressing much further, I'll talk about how to manipulate these sets. Each set is of the type fd_set. The following macros operate on this type:

  • FD_ZERO(fd_set *set) - clears a file descriptor set
  • FD_SET(int fd, fd_set *set) - adds fd to the set
  • FD_CLR(int fd, fd_set *set) - removes fd from the set
  • FD_ISSET(int fd, fd_set *set) - tests to see if fd is in the set
Finally, what is this weirded out struct timeval? Well, sometimes you don't want to wait forever for someone to send you some data. Maybe every 96 seconds you want to print "Still Going..." to the terminal even though nothing has happened. This time structure allows you to specify a timeout period. If the time is exceeded and select() still hasn't found any ready file descriptors, it'll return so you can continue processing.

The struct timeval has the follow fields:

struct timeval {
    int tv_sec;     /* seconds */
    int tv_usec;    /* microseconds */
};

Just set tv_sec to the number of seconds to wait, and set tv_usec to the number of microseconds to wait. Yes, that's microseconds, not milliseconds. There are 1,000 microseconds in a millisecond, and 1,000 milliseconds in a second. Thus, there are 1,000,000 microseconds in a second. Why is it "usec"? The "u" is supposed to look like the Greek letter Mu that we use for "micro". Also, when the function returns, timeout might be updated to show the time still remaining. This depends on what flavor of Unix you're running.

Yay! We have a microsecond resolution timer! Well, don't count on it. Standard Unix timeslice is 100 milliseconds, so you'll probably have to wait at least that long, no matter how small you set your struct timeval.

Other things of interest: If you set the fields in your struct timeval to 0, select() will timeout immediately, effectively polling all the file descriptors in your sets. If you set the parameter timeout to NULL, it will never timeout, and will wait until the first file descriptor is ready. Finally, if you don't care about waiting for a certain set, you can just set it to NULL in the call to select().

The following code snippet waits 2.5 seconds for something to appear on standard input:

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

#define STDIN 0  /* file descriptor for standard input */

main()
{
  struct timeval tv;
  fd_set readfds;

  tv.tv_sec = 2;
  tv.tv_usec = 500000;

  FD_ZERO(&readfds);
  FD_SET(STDIN, &readfds);

  /* don't care about writefds and exceptfds: */
  select(STDIN+1, &readfds, NULL, NULL, &tv);

  if (FD_ISSET(STDIN, &readfds))
    printf("A key was pressed!\n");
  else
    printf("Timed out.\n");
  }

If you're on a line buffered terminal, the key you hit should be RETURN or it will time out anyway.

Now, some of you might think this is a great way to wait for data on a datagram socket -- and you are right: it might be. Some Unices can use select in this manner, and some can't. You should see what your local man page says on the matter if you want to attempt it.

One final note of interest about select(): if you have a socket that is listen()'ing, you can check to see if there is a new connection by putting that socket's file descriptor in the readfds set.

And that, my friends, is a quick overview of the almighty select() function.


Prev | Up | Next


Copyright © 1995, 1996 by Brian "Beej" Hall. This guide may be reprinted in any medium provided that its content is not altered, it is presented in its entirety, and this copyright notice remains intact. Contact beej@ecst.csuchico.edu for more information.

SELECT is an SQL command for retrieving data from a (relational) database. The simplest SELECT statement is this:

SELECT * FROM example

The statement above tells the database to return all data in the table called example, with the rows in no particular order. To limit the amount of data that is returned you can specify which fields in the table to return, and you can set conditions on the rows that are returned with a WHERE clause.

SELECT nickname, firstname, lastname FROM example WHERE nickname='nate'

The statement above will return all rows that have the value 'nate' in the field nickname. Each returned row only contains data from the fields nickname, firstname and lastname.

SELECT nickname, firstname, lastname FROM example ORDER BY lastname

If you include the ORDER BY clause, then the rows will be sorted by the field(s) in the ORDER BY clause. If you add DESC after the field name(s), then the rows are sorted in descending order.

You can do much more with SELECT statements, such as selecting from more than one table (called joining), but unfortunately the syntax sometimes varies depending on which database server you use.

See LIKE for information on how to perform pattern matching.

Se*lect" (?), a. [L. selectus, p. p. of seligere to select; pref. se- aside + levere to gather. See Legend.]

Taken from a number by preferance; picked out as more valuable or exellent than others; of special value or exellence; nicely chosen; selected; choice.

A few select spirits had separated from the crowd, and formed a fit audience round a far greater teacher. Macaulay.

 

© Webster 1913.


Se*lect", v. t. [imp. & p. p. Selected; p. pr. & vb. n. Selecting.]

To choose and take from a number; to take by preference from among others; to pick out; to cull; as, to select the best authors for perusal.

"One peculiar nation to select."

Milton.

The pious chief . . . A hundred youths from all his train selects. Dryden.

 

© Webster 1913.

Log in or register to write something here or to contact authors.