WSAAsyncSelect
The Windows
Sockets WSAAsyncSelect function requests Windows message-based
notification of network events for a socket.
int WSAAsyncSelect (
SOCKET s, |
|
HWND hWnd, |
|
unsigned
int wMsg, |
|
long lEvent |
|
); |
|
Parameters
s
[in] A
descriptor identifying the socket for which event notification is required.
hWnd
[in] A handle
identifying the window which should receive a message when a network event
occurs.
wMsg
[in] The
message to be received when a network event occurs.
lEvent
[in] A
bitmask which specifies a combination of network events in which the application
is interested.
Remarks
This function
is used to request that the Windows Sockets DLL should send a message to the
window hWnd whenever it detects any of the network events specified by
the lEvent parameter. The message which should be sent is specified by
the wMsg parameter. The socket for which notification is required is
identified by s.
This function
automatically sets socket s to nonblocking mode, regardless of the value
of lEvent. See ioctlsocket about how to set the nonoverlapped
socket back to blocking mode.
The lEvent
parameter is constructed by or'ing any of the values specified in the following
list.
Value |
Meaning |
FD_READ |
Want to
receive notification of readiness for reading |
FD_WRITE |
Want to
receive notification of readiness for writing |
FD_OOB |
Want to
receive notification of the arrival of out-of-band data |
FD_ACCEPT |
Want to
receive notification of incoming connections |
FD_CONNECT |
Want to
receive notification of completed connection |
FD_CLOSE |
Want to
receive notification of socket closure |
FD_QOS |
Want to
receive notification of socket Quality of Service (QOS) changes |
FD_GROUP_QOS |
Want to
receive notification of socket group Quality of Service (QOS) changes |
Issuing a WSAAsyncSelect
for a socket cancels any previous WSAAsyncSelect or WSAEventSelect
for the same socket. For example, to receive notification for both reading and
writing, the application must call WSAAsyncSelect with both FD_READ and
FD_WRITE, as follows:
rc = WSAAsyncSelect(s, hWnd, wMsg,
FD_READ|FD_WRITE);
It is not
possible to specify different messages for different events. The following code
will not work; the second call will cancel the effects of the first, and only
FD_WRITE events will be reported with message wMsg2:
rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ);
rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);
To cancel all
notification (that is, to indicate that Windows Sockets should send no further
messages related to network events on the socket) lEvent should be set
to zero.
rc = WSAAsyncSelect(s, hWnd, 0, 0);
Although in
this instance WSAAsyncSelect immediately disables event message posting
for the socket, it is possible that messages can be waiting in the
application's message queue. The application must therefore be prepared to
receive network event messages even after cancellation. Closing a socket with closesocket
also cancels WSAAsyncSelect message sending, but the same caveat about
messages in the queue prior to the closesocket still applies.
Since an accept'ed
socket has the same properties as the listening socket used to accept it, any WSAAsyncSelect
events set for the listening socket apply to the accepted socket. For example,
if a listening socket has WSAAsyncSelect events FD_ACCEPT, FD_READ, and
FD_WRITE, then any socket accepted on that listening socket will also have
FD_ACCEPT, FD_READ, and FD_WRITE events with the same wMsg value used
for messages. If a different wMsg or events are desired, the application
should call WSAAsyncSelect, passing the accepted socket and the desired
new information.
When one of
the nominated network events occurs on the specified socket s, the
application's window hWnd receives message wMsg. The wParam
argument identifies the socket on which a network event has occurred. The low
word of lParam specifies the network event that has occurred. The high
word of lParam contains any error code. The error code be any error as
defined in WINSOCK2.H.
Note Upon receipt
of an event notification message the WSAGetLastError function cannot be
used to check the error value, because the error value returned can differ from
the value in the high word of lParam.
The error and
event codes can be extracted from the lParam using the macros
WSAGETSELECTERROR and WSAGETSELECTEVENT, defined in WINSOCK2.H as:
#define WSAGETSELECTERROR(lParam) HIWORD(lParam)
#define WSAGETSELECTEVENT(lParam) LOWORD(lParam)
The use of
these macros will maximize the portability of the source code for the
application.
The possible
network event codes which can be returned are as follows:
Value |
Meaning |
FD_READ |
Socket s
ready for reading |
FD_WRITE |
Socket s
ready for writing |
FD_OOB |
Out-of-band
data ready for reading on socket s |
FD_ACCEPT |
Socket s
ready for accepting a new incoming connection |
FD_CONNECT |
Connection
initiated on socket s completed |
FD_CLOSE |
Connection
identified by socket s has been closed |
FD_QOS |
Quality of
Service associated with socket s has changed |
FD_GROUP_QOS |
Quality of
Service associated with the socket group to which s belongs has
changed |
Return Values
The return
value is zero if the application's declaration of interest in the network event
set was successful. Otherwise, the value SOCKET_ERROR is returned, and a
specific error number can be retrieved by calling WSAGetLastError.
Comments
Although WSAAsyncSelect
can be called with interest in multiple events, the application window will
receive a single message for each network event.
As in the
case of the select function, WSAAsyncSelect will frequently be
used to determine when a data transfer operation (send or recv)
can be issued with the expectation of immediate success. Nevertheless, a robust
application must be prepared for the possibility that it can receive a message
and issue a Windows Sockets 2 call which returns WSAEWOULDBLOCK immediately.
For example, the following sequence of events is possible:
1. data arrives on socket s; Windows
Sockets 2 posts WSAAsyncSelect message
2. application processes some other message
3. while processing, application issues an ioctlsocket(s,
FIONREAD...) and notices that there is data ready to be read
4. application issues a recv(s,...) to
read the data
5. application loops to process next message,
eventually reaching the WSAAsyncSelect message indicating that data is
ready to read
6. application issues recv(s,...), which
fails with the error WSAEWOULDBLOCK.
Other
sequences are possible.
The Windows
Sockets DLL will not continually flood an application with messages for a
particular network event. Having successfully posted notification of a
particular event to an application window, no further message(s) for that
network event will be posted to the application window until the application
makes the function call which implicitly re-enables notification of that
network event.
Event |
Re-enabling
function |
FD_READ |
recv, recvfrom, WSARecv, or WSARecvFrom |
FD_WRITE |
send, sendto, WSASend, or WSASendTo |
FD_OOB |
recv, recvfrom, WSARecv, or WSARecvFrom |
FD_ACCEPT |
accept or WSAAccept unless the error code is
WSATRY_AGAIN indicating that the condition function returned CF_DEFER |
FD_CONNECT |
NONE |
FD_CLOSE |
NONE |
FD_QOS |
WSAIoctl with command SIO_GET_QOS |
FD_GROUP_QOS |
WSAIoctl with command SIO_GET_GROUP_QOS |
Any call to
the re-enabling routine, even one which fails, results in re-enabling of
message posting for the relevant event.
For FD_READ,
FD_OOB, and FD_ACCEPT events, message posting is "level-triggered."
This means that if the re-enabling routine is called and the relevant condition
is still met after the call, a WSAAsyncSelect message is posted to the
application. This allows an application to be event-driven and not be concerned
with the amount of data that arrives at any one time. Consider the following
sequence:
1. Network transport stack receives 100 bytes of
data on socket s and causes Windows Sockets 2 to post an FD_READ
message.
2. The application issues recv( s, buffptr,
50, 0) to read 50 bytes.
3. Another FD_READ message is posted since there is
still data to be read.
With these
semantics, an application need not read all available data in response to an
FD_READ messagea single recv in response to each FD_READ message is
appropriate. If an application issues multiple recv calls in response to
a single FD_READ, it can receive multiple FD_READ messages. Such an application
may need to disable FD_READ messages before starting the recv calls by
calling WSAAsyncSelect with the FD_READ event not set.
The FD_QOS
and FD_GROUP_QOS events are considered edge triggered. A message will be posted
exactly once when a QOS change occurs. Further messages will not be forthcoming
until either the provider detects a further change in QOS or the application
renegotiates the QOS for the socket.
If any event
has already happened when the application calls WSAAsyncSelect or when
the re-enabling function is called, then a message is posted as appropriate.
For example, consider the following sequence:
1. an application calls listen,
2. a connect request is received but not yet
accepted,
3. the application calls WSAAsyncSelect
specifying that it wants to receive FD_ACCEPT messages for the socket. Due to
the persistence of events, Windows Sockets 2 posts an FD_ACCEPT message
immediately.
The FD_WRITE
event is handled slightly differently. An FD_WRITE message is posted when a
socket is first connected with connect/WSAConnect (after FD_CONNECT, if
also registered) or accepted with accept/WSAAccept, and then after a
send operation fails with WSAEWOULDBLOCK and buffer space becomes available.
Therefore, an application can assume that sends are possible starting from the
first FD_WRITE message and lasting until a send returns WSAEWOULDBLOCK. After
such a failure the application will be notified that sends are again possible
with an FD_WRITE message.
The FD_OOB
event is used only when a socket is configured to receive out-of-band data
separately. (See section Out-Of-Band data
The error
code in an FD_CLOSE message indicates whether the socket close was graceful or
abortive. If the error code is zero, then the close was graceful; if the error
code is WSAECONNRESET, then the socket's virtual circuit was reset. This only
applies to connection-oriented sockets such as SOCK_STREAM.
The FD_CLOSE
message is posted when a close indication is received for the virtual circuit
corresponding to the socket. In TCP terms, this means that the FD_CLOSE is
posted when the connection goes into the TIME WAIT or CLOSE WAIT states. This
results from the remote end performing a shutdown on the send side or a closesocket.
FD_CLOSE should only be posted after all data is read from a socket, but an
application should check for remaining data upon receipt of FD_CLOSE to avoid
any possibility of losing data.
Please note
your application will receive ONLY an FD_CLOSE message to indicate closure of a
virtual circuit, and only when all the received data has been read if this is a
graceful close. It will not receive an FD_READ message to indicate this
condition.
The FD_QOS or
FD_GROUP_QOS message is posted when any field in the flow specification
associated with socket s or the socket group that s belongs to
has changed, respectively. Applications should use WSAIoctl with command
SIO_GET_QOS or SIO_GET_GROUP_QOS to get the current QOS for socket s or
for the socket group s belongs to, respectively.
Here is a
summary of events and conditions for each asynchronous notification message:
FD_READ:
1. when WSAAsyncSelect called, if there is data currently
available to receive,
2. when data arrives, if FD_READ not already posted,
3. after recv or recvfrom called (with or without
MSG_PEEK), if data is still available to receive.
Note when setsockopt SO_OOBINLINE is
enabled "data" includes both normal data and out-of-band (OOB) data
in the instances noted above.
FD_WRITE:
1. when WSAAsyncSelect called, if a send or sendto
is possible
2. after connect or accept called, when connection
established
3. after send or sendto fail with WSAEWOULDBLOCK, when send
or sendto are likely to succeed,
4. after bind on a datagram socket.
FD_OOB: Only valid when setsockopt
SO_OOBINLINE is disabled (default).
1. when WSAAsyncSelect called, if there is OOB data currently
available to receive with the MSG_OOB flag,
2. when OOB data arrives, if FD_OOB not already posted,
3. after recv or recvfrom called with or without
MSG_OOB flag, if OOB data is still available to receive.
FD_ACCEPT:
1. when WSAAsyncSelect called, if there is currently a
connection request available to accept,
2. when a connection request arrives, if FD_ACCEPT not already posted,
3. after accept called, if there is another connection request
available to accept.
FD_CONNECT:
1. when WSAAsyncSelect called, if there is currently a
connection established,
2. after connect called, when connection is established (even
when connect succeeds immediately, as is typical with a datagram socket)
FD_CLOSE: Only valid on
connection-oriented sockets (for example, SOCK_STREAM)
1. when WSAAsyncSelect called, if socket connection has been
closed,
2. after remote system initiated graceful close, when no data currently
available to receive (note: if data has been received and is waiting to be read
when the remote system initiates a graceful close, the FD_CLOSE is not
delivered until all pending data has been read),
3. after local system initiates graceful close with shutdown
and remote system has responded with "End of Data" notification (for
example, TCP FIN), when no data currently available to receive,
4. when remote system terminates connection (for example, sent TCP
RST), and lParam will contain WSAECONNRESET error value.
Note FD_CLOSE is not posted after closesocket
is called.
FD_QOS:
1. when WSAAsyncSelect called, if the QOS associated with the
socket has been changed,
2. after WSAIoctl with SIO_GET_QOS called, when the QOS is changed.
FD_GROUP_QOS:
1. when WSAAsyncSelect called, if the group QOS associated with
the socket has been changed,
2. after WSAIoctl with SIO_GET_GROUP_QOS called, when the group
QOS is changed.
Error Codes
WSANOTINITIALISED |
A
successful WSAStartup must occur before using this function. |
WSAENETDOWN |
The network
subsystem has failed. |
WSAEINVAL |
Indicates
that one of the specified parameters was invalid such as the window handle
not referring to an existing window, or the specified socket is in an invalid
state. |
WSAEINPROGRESS |
A blocking
Windows Sockets 1.1 call is in progress, or the service provider is still
processing a callback function. |
WSAENOTSOCK |
The
descriptor is not a socket. |
Additional
error codes may be set when an application window receives a message. This
error code is extracted from the lParam in the reply message using the
WSAGETSELECTERROR macro. Possible error codes for each network event are:
Event:
FD_CONNECT
Error
Code |
Meaning |
WSAEADDRINUSE |
The
specified address is already in use. |
WSAEADDRNOTAVAIL |
The
specified address is not available from the local machine. |
WSAEAFNOSUPPORT |
Addresses
in the specified family cannot be used with this socket. |
WSAECONNREFUSED |
The attempt
to connect was forcefully rejected. |
WSAENETUNREACH |
The network
cannot be reached from this host at this time. |
WSAEFAULT |
The namelen
argument is incorrect. |
WSAEINVAL |
The socket
is already bound to an address. |
WSAEISCONN |
The socket
is already connected. |
WSAEMFILE |
No more
file descriptors are available. |
WSAENOBUFS |
No buffer
space is available. The socket cannot be connected. |
WSAENOTCONN |
The socket
is not connected. |
WSAETIMEDOUT |
Attempt to
connect timed out without establishing a connection. |
Event:
FD_CLOSE
Error
Code |
Meaning |
WSAENETDOWN |
The network
subsystem has failed. |
WSAECONNRESET |
The
connection was reset by the remote side. |
WSAECONNABORTED |
The
connection was terminated due to a time-out or other failure. |
Event:
FD_READ
Event:
FD_WRITE
Event:
FD_OOB
Event:
FD_ACCEPT
Event:
FD_QOS
Event:
FD_GROUP_QOS
Error
Code |
Meaning |
WSAENETDOWN |
The network
subsystem has failed. |
See Also