4.1.18 select()
Description
Determine the status of one or more sockets, waiting if necessary.
#include <winsock.h>
int PASCAL FAR select ( int nfds, fd_set FAR * readfds, fd_set FAR * writefds,
fd_set FAR * exceptfds, const struct timeval FAR * timeout );
nfds
This argument is ignored and included only for the sake of compatibility.
readfds
An optional pointer to a set of sockets to be checked for readability.
writefds
An optional pointer to a set of sockets to be checked for writability
exceptfds
An optional pointer to a set of sockets to be checked for errors.
timeout
The maximum time for select() to wait, or NULL for blocking operation.
Remarks
This function is used to determine the status of one or more sockets. For each
socket, the caller may request information on read, write or error status. The
set of sockets for which a given status is requested is indicated by an fd_set
structure. Upon return, the structure is updated to reflect the subset of these
sockets which meet the specified condition, and select() returns the number of
sockets meeting the conditions. A set of macros is provided for manipulating an
fd_set. These macros are compatible with those used in the Berkeley software,
but the underlying representation is completely different.
The parameter readfds identifies those sockets which are to be checked for
readability. If the socket is currently listen()ing, it will be marked as
readable if an incoming connection request has been received, so that an
accept() is guaranteed to complete without blocking. For other sockets,
readability means that queued data is available for reading or, for sockets of
type SOCK_STREAM, that the virtual socket corresponding to the socket has been
closed, so that a recv() or recvfrom() is guaranteed to complete without
blocking. If the virtual circuit was closed gracefully, then a recv() will
return immediately with 0 bytes read; if the virtual circuit was reset, then a
recv() will complete immediately with the error code WSAECONNRESET. The presence
of out-of-band data will be checked if the socket option SO_OOBINLINE has been
enabled (see setsockopt()).
The parameter writefds identifies those sockets which are to be checked for
writability. If a socket is connect()ing (non-blocking), writability means that
the connection establishment successfully completed. If the socket is not in the
process of connect()ing, writability means that a send() or sendto() will
complete without blocking. [It is not specified how long this guarantee can be
assumed to be valid, particularly in a multithreaded environment.]
The parameter exceptfds identifies those sockets which are to be checked for the
presence of out-of-band data or any exceptional error conditions. Note that
out-of-band data will only be reported in this way if the option SO_OOBINLINE is
FALSE. For a SOCK_STREAM, the breaking of the connection by the peer or due to
KEEPALIVE failure will be indicated as an exception. This specification does not
define which other errors will be included. If a socket is connect()ing
(non-blocking), failure of the connect attempt is indicated in exceptfds.
Any of readfds, writefds, or exceptfds may be given as NULL if no descriptors
are of interest.
Four macros are defined in the header file winsock.h for manipulating the
descriptor sets. The variable FD_SETSIZE determines the maximum number of
descriptors in a set. (The default value of FD_SETSIZE is 64, which may be
modified by #defining FD_SETSIZE to another value before #including winsock.h.)
Internally, an fd_set is represented as an array of SOCKETs; the last valid
entry is followed by an element set to INVALID_SOCKET. The macros are:
FD_CLR(s, *set) Removes the descriptor s from set.
FD_ISSET(s, *set) Nonzero if s is a member of the set, zero otherwise.
FD_SET(s, *set) Adds descriptor s to set.
FD_ZERO(*set) Initializes the set to the NULL set.
The parameter timeout controls how long the select() may take to complete. If
timeout is a null pointer, select() will block indefinitely until at least one
descriptor meets the specified criteria. Otherwise, timeout points to a struct
timeval which specifies the maximum time that select() should wait before
returning. If the timeval is initialized to {0, 0}, select() will return
immediately; this is used to "poll" the state of the selected sockets. If this
is the case, then the select() call is considered nonblocking and the standard
assumptions for nonblocking calls apply. For example, the blocking hook must not
be called, and the Windows Sockets implementation must not yield.
Return Value
select() returns the total number of descriptors which are ready and contained
in the fd_set structures, 0 if the time limit expired, or SOCKET_ERROR if an
error occurred. If the return value is SOCKET_ERROR, WSAGetLastError() may be
used to retrieve a specific error code.
Error Codes
WSANOTINITIALISED
WSAENETDOWN
WSAEINVAL
WSAEINTR
WSAEINPROGRESS
WSAENOTSOCK
A successful WSAStartup() must occur before using this API.
The Windows Sockets implementation has detected that the network subsystem has
failed.
The timeout value is not valid.
The (blocking) call was canceled via WSACancelBlockingCall().
A blocking Windows Sockets operation is in progress.
One of the descriptor sets contains an entry which is not a socket.
T...
3.1.1 Blocking/Non blocking & Data Volatility
One major issue in porting applications from a Berkeley sockets environment to a
Windows environment involves "blocking"; that is, invoking a function which does
not return until the associated operation is completed. The problem arises when
the operation may take an arbitrarily long time to complete: an obvious example
is a recv() which may block until data has been received from the peer system.
The default behavior within the Berkeley sockets model is for a socket to
operate in a blocking mode unless the programmer explicitly requests that
operations be treated as non-blocking. It is strongly recommended that
programmers use the nonblocking (asynchronous) operations if at all possible, as
they work significantly better within the nonpreemptive Windows environment. Use
blocking operations only if absolutely necessary, and carefully read and
understand this section if you must use blocking operations.
Even on a blocking socket, some operations (e.g. bind(), getsockopt(),
getpeername()) can be completed immediately. For such operations there is no
difference between blocking and non-blocking operation. Other operations (e.g.
recv()) may be completed immediately or may take an arbitrary time to complete,
depending on various transport conditions. When applied to a blocking socket,
these operations are referred to as blocking operations. All routines which can
block are listed with an asterisk in the tables above and below.
Within a Windows Sockets implementation, a blocking operation which cannot be
completed immediately is handled as follows. The DLL initiates the operation,
and then enters a loop in which it dispatches any Windows messages (yielding the
processor to another thread if necessary) and then checks for the completion of
the Windows Sockets function. If the function has completed, or if
WSACancelBlockingCall() has been invoked, the blocking function completes with
an appropriate result. Refer to section 4.3.13, WSASetBlockingHook(), for a
complete description of this mechanism, including pseudocode for the various
functions.
If a Windows message is received for a process for which a blocking operation is
in progress, there is a risk that the application will attempt to issue another
Windows Sockets call. Because of the difficulty of managing this condition
safely, the Windows Sockets specification does not support such application
behavior. Two functions are provided to assist the programmer in this situation.
WSAIsBlocking() may be called to determine whether or not a blocking Windows
Sockets call is in progress. WSACancelBlockingCall() may be called to cancel an
in-progress blocking call, if any. Any other Windows Sockets function which is
called in this situation will fail with the error WSAEINPROGRESS. It should be
emphasized that this restriction applies to both blocking and non-blocking
operations.
Although this mechanism is sufficient for simple applications, it cannot support
the complex message-dispatching requirements of more advanced applications (for
example, those using the MDI model). For such applications, the Windows Sockets
API includes the function WSASetBlockingHook(), which allows the programmer to
define a special routine which will be called instead of the default message
dispatch routine described above.
The Windows Sockets DLL calls the blocking hook only if all of the following are
true: the routine is one which is defined as being able to block, the specified
socket is a blocking socket, and the request cannot be completed immediately. (A
socket is set to blocking by default, but the IOCTL FIONBIO and WSAAsyncSelect()
both set a socket to nonblocking mode.) If an application uses only non-blocking
sockets and uses the WSAAsyncSelect() and/or the WSAAsyncGetXByY() routines
instead of select() and the getXbyY() routines, then the blocking hook will
never be called and the application does not need to be concerned with the
reentrancy issues the blocking hook can introduce.
If an application invokes an asynchronous or non-blocking operation which takes
a pointer to a memory object (e.g. a buffer, or a global variable) as an
argument, it is the responsibility of the application to ensure that the object
is available to the Windows Sockets implementation throughout the operation. The
application must not invoke any Windows function which might affect the mapping
or addressability of the memory involved. In a multithreaded system, the
application is also responsible for coordinating access to the object using
appropriate synchronization mechanisms. A Windows Sockets implementation cannot,
and will not, address these issues. The possible consequences of failing to
observe these rules are beyond the scope of this specification.