select Function

 < Day Day Up > 



select Function

The select function provides a notification service for a collection of events on one or more sockets. Given a set of socket descriptors, the select function can be used to determine if data is available to read, space is available in the send buffer for write, or if an error occurred (otherwise known as an exception). Additionally, the select function can be configured to return after some amount of time if no events have occurred.

The select function has the following prototype:

#include <sys/select.h> #include <sys/time.h> int select( int num, fd_set *readsds, fd_set *writesds,                fd_set *exceptfds, struct timeval *timeout );

The num argument here refers to the number of socket descriptors that are present in the fd_set structures (plus one). The fd_set structure is an array of bit fields whose manipulation is masked by a set of functions (we look at these in the following paragraphs). Three of the fd_set structures are shown, one for read events, one for write events, and one for exceptions. The final argument, timeout, is used to define a timeout value for the select function. We look at this structure in more detail shortly. The return value for select is shown in Table 4.2.

Table 4.2: RETURN VALUES FOR THE select FUNCTION

Value

Description

> 0

Number of descriptors that are contained within the descriptor sets

0

Expiration of the timeout argument

-1

An error occurred in the select function

The fd_set manipulation functions are discussed next. These functions permit a developer to enable, set, or clear a socket for a given event, test whether an event occurred for a socket, and clear the events within a given fd_set structure.

 FD_CLR( int socket, fd_set *set ); FD_SET( int socket, fd_set *set ); FD_ISSET( int socket, fd_set *set ); FD_ZERO( fd_set *set );

The FD_CLR function is used to remove a socket descriptor from a set, whereas the FD_SET function adds a socket descriptor to the set for notification. The FD_ISSET function is used to test whether the particular descriptor was in the response set, and is used after the select function returns. Finally, the FD_ZERO function is used to clear out the set structure. This function is commonly used before the socket descriptors of interest are set using the FD_SET function.

Using the select function is quite simple, though select is commonly not used in high performance applications due to its inherent inefficiency. Applications that use select typically follow a similar model. First, the descriptor sets are defined for the events for which notification is needed. Note that not all of the sets must be defined; if the application was interested only in read events, only this set need be specified. For each event set of interest, the set is cleared using FD_ZERO. Next, for each of the socket descriptors to be monitored, the FD_SET function is called for the particular event set. Note that a socket descriptor may be specified in more than one event set (for example, if read and exception events were desired for the socket). If a timeout is needed, the timeout parameter is also defined. Upon return, the FD_ISSET function is used to determine which sockets reported which events and then take whatever action is necessary.

Let’s now look at a simple example of the select function. This example illustrates notification on a read and exception event for a given socket (see Listing 4.1).

Listing 4.1 Simple example of the select function for a read event.

start example
fd_set read_set, exc_set; int sock; int ret; ... /* Set up our read events */ FD_ZERO( &read_set ); FD_SET( sock, &read_set ); /* Set up our exception events */ FD_ZERO( &exc_set ); FD_SET( sock, &exc_set ); ret = select( sock+1, &read_set, NULL, &exc_set, NULL ); if (ret > 0) {   if        (FD_ISSET( sock, &read_set )) {     /* Read event for socket sock */   } else if (FD_ISSET( sock, &exc_set )) {     /* Exception event for socket sock */   } } else {   /* An error occurred */ }
end example

In the very simple example from Listing 4.1, we enable a read event and an exception event for our socket (represented by sock) and then call select. Note that we specify the first argument as sock+1, because this must be exactly one greater than the largest socket descriptor that was loaded in the socket descriptor sets. Because we’re looking for read events and exception events, we pass in our read set structure as argument 2, and then our exception set as argument 4 (both as references, because the select function will modify these sets). We’re not looking for write events, so we pass a NULL for this argument of select. We also have no timeout constraints for the select function, so we pass a NULL for timeout as well. Upon return from select, we check the return value, and if greater than zero, we know that one or more events were triggered. We then use the FD_ISSET function to test which event actually fired. Otherwise, a return value less than zero indicates an error, and should be treated accordingly (commonly, a bad socket was passed in to one of the sets).

Let’s now look at another example that utilizes the timeout feature of select. In this example, we’ll try to read from a socket for 10 seconds, and if no data is read within that time, we’ll time out the select call and perform some other action (see Listing 4.2).

Listing 4.2 Simple select example for read events with a timeout.

start example
fd_set read_set; struct timeval to; int sock, ret; ... /* Set up our read event */ FD_ZERO( &read_set ); FD_SET( sock, &read_set ); /* Set up our timeout */ to.tv_sec = 10; to.tv_usec = 0; ret = select( sock+1, &read_set, NULL, NULL, &to); if (ret == 0) {   /* Timeout occurred */ } else if (ret > 0) {   if (FD_ISSET( sock, &read_set )) {     /* Read event for socket sock */   } } else {   /* An error occurred */ }
end example

The difference to note in Listing 4.2 is that we create a new variable called to, which is a structure of type timeval. This contains a tv_sec field to represent time in seconds, and a tv_usec field for microsecond time values. These are loaded, in this example, for 10 seconds. We pass the timeout argument as a reference in this example, and then check for a zero return after select, which indicates a timeout occurred. What happens to timeout values when a read event occurs before the timeout value is reached? Linux systems place the remaining time left in the to argument, which could then be used to pass back into the select function to keep regular timeout intervals. This is sloppy time-wise, but better than restarting the timeout with each call to select.

Another common use of the select function is that of time delay. Because the event sets can all be set to NULL, the application can call select as follows:

/* Set up our timeout */ to.tv_sec = 0; to.tv_usec = 100000; ret = select( 0, NULL, NULL, NULL, &to); if (ret == 0) {   /* Timeout */ }

In this example, the select call will return after approximately 100 milliseconds. In Linux, any file descriptor can be set in the event sets (socket descriptors or file descriptors). Therefore, the application can multiplex across not only event types, but also medium types. The Windows operating system provides only support for sockets within the context of select.

In addition to looking for read, write, and exception events, the select call can be used for other types of socket events. For example, a read event is generated on a socket if the peer closed its end of the socket connection. An application can also detect whether an accept call needs to be performed on a listening socket (to avoid blocking on the accept call). In this case, a read event on a listening (server) socket indicates that one or more client connections are awaiting accept. Write events can detect peer closures in addition to buffer space available for the socket write buffer. Another use is to detect the completion of a socket connect from a client to a server.



 < Day Day Up > 



BSD Sockets Programming from a Multi-Language Perspective
Network Programming for Microsoft Windows , Second Edition (Microsoft Programming Series)
ISBN: 1584502681
EAN: 2147483647
Year: 2003
Pages: 225
Authors: Jim Ohlund

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net