Description
Request event notification for a socket.
#include <winsock.h>
int PASCAL FAR WSAAsyncSelect ( SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent );
s
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. The lEvent parameter is constructed by or'ing any of the values specified in the following list.
FD_READ
Issuing a WSAAsyncSelect() for a socket cancels any previous WSAAsyncSelect() 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 -- i.e., to indicate that the Windows Sockets implementation 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 may 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.
φNote: There is a timing window between the accept() call and the call to WSAAsyncSelect() to change the events or wMsg. An application which desires a different wMsg for the listening and accept()'ed sockets should ask for only FD_ACCEPT events on the listening socket, then set appropriate events after the accept(). Since FD_ACCEPT is never sent for a connected socket and FD_READ, FD_WRITE, FD_OOB, and FD_CLOSE are never sent for listening sockets, this will not impose difficulties.∙
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 winsock.h.
The error and event codes may be extracted from the lParam using the macros WSAGETSELECTERROR and WSAGETSELECTEVENT, defined in winsock.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 may be returned are as follows:
FD_READ
Return Value
The return value is 0 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 may 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 may receive a message and issue a Windows Sockets API call which returns WSAEWOULDBLOCK immediately. For example, the following sequence of events is possible:
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.
FD_READ
Any call to the reenabling routine, even one which fails, results in reenabling of message posting for the relevent event.
For FD_READ, FD_OOB, and FD_ACCEPT events, message posting is "level-triggerred." This means that if the reenabling routine is called and the relevent event is still valid after the call, a WSAAsyncSelect() message is posted to the application. This allows an application to be event-driven and not concern itself with the amount of data that arrives at any one time. Consider the following sequence:
With these semantics, an application need not read all available data in response to an FD_READ message--a 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 may receive multiple FD_READ messages. Such an application may wish to disable FD_READ messages before starting the recv() calls by calling WSAAsyncSelect() with the FD_READ event not set.
If an event is true when the application initially calls WSAAsyncSelect() or when the reenabling function is called, then a message is posted as appropriate. For example, if an application calls listen(), a connect attempt is made, then the application calls WSAAsyncSelect() specifying that it wants to receive FD_ACCEPT messages for the socket, the Windows Sockets implementation 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() or accepted with accept(), and then after a send() or sendto() 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. If the socket is configured to receive out-of-band data in-line, the out-of-band (expedited) data is treated as normal data and the application should register an interest in, and will receive, FD_READ events, not FD_OOB events. An application may set or inspect the way in which out-of-band data is to be handled by using setsockopt() or getsockopt for the SO_OOBINLINE option.
The error code in an FD_CLOSE message indicates whether the socket close was graceful or abortive. If the error code is 0, then the close was graceful; if the error code is WSAECONNRESET, then the socket's virtual socket was abortively disconnected. This only applies to sockets of type 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 FIN WAIT or CLOSE WAIT states. This results from the remote end performing a shutdown() on the send side or a closesocket().
Please note your application will receive ONLY an FD_CLOSE message to indicate closure of a virtual circuit. It will NOT receive an FD_READ message to indicate this condition.
Error Codes
WSANOTINITIALISED
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 Codes
WSAEADDRINUSE
Event: FD_CLOSE
Error Codes
WSAENETDOWN
Event: FD_READ Event: FD_WRITE
Event: FD_OOB
Event: FD_ACCEPT
Error Code
WSAENETDOWN
Notes For Windows Sockets Suppliers
It is the responsibility of the Windows Sockets Supplier to ensure that messages are successfully posted to the application. If a PostMessage() operation fails, the Windows Sockets implementation must re-post that message as long as the window exists.
Windows Sockets suppliers should use the WSAMAKESELECTREPLY macro when constructing the lParam in the message. When a socket is closed, the Windows Sockets Supplier should purge any messages remaining for posting to the application window. However the application must be prepared to receive, and discard, any messages which may have been posted prior to the closesocket().
See Also