Just as simple network operations like recv() can block for extended periods of time, so can the database routines like gethostbyname(), especially is they go through DNS which can require considerable time due to the network activity involved. In order to allow well-behaved Windows Applications to use the database routines, the Windows Sockets API supplies asynchronous versions of the database routines. Their use is similar to the synchronous database routines with two important exceptions:
In order to make an asynchronous database call, an application passes in information about the call, a window handle to receive the completion message, a message code, and a buffer for the output information. The Windows Sockets API defines a constant, MAXGETHOSTSTRUCT, which is the maximum size of a hostent structure. An application should use a buffer of this size to pass to the asynchronous database routines in order to be guaranteed that all the output information will fit in its buffer. A call to WSAAsyncGetHostByName() may be as follows:
#define GETHOST_MESSAGE WM_USER+2 BYTE HostBuffer[MAXGETHOSTSTUCT]; HANDLE TaskHandle; /* Resolve hostname "hostname" asynchronously */ TaskHandle = WSAAsyncGetHostByName(hWnd, GETHOST_MESSAGE, "hostname", HostBuffer, MAXGETHOSTSTUCT); if (TaskHandle == SOCKET_ERROR) { sprintf(buf, "Windows Sockets error %d: Hostname couldn't be resolved.", WSAGetLastError()); MessageBox(hWnd,buf,"Windows Sockets Error",MB_OK); shutdown_appl(); }
WSAAsyncGetHostByName() and the other asynchronous database routines return a "task handle" which uniquely refers to the operation in progress. This task handle allows an application which may have multiple outstanding asynchronous database routines to associate completion messages with the request, since the task handle is returned in the completion message as wParam.
To receive and process the completion message, an application will do the following in its window procedure:
long FAR PASCAL _export WndProc(HWND hWnd, UINT message, UINT wParam, LONG lParam) { INT err; switch (message) { case ...: /* handle Windows messages */ . . . case GETHOST_MESSAGE: /* An asynchronous database routine completed. */ if (WSAGETASYNCERROR(lParam) != 0) { sprintf(buf, "Windows Sockets error %d: Hostname couldn't be resolved.", WSAGetLastError()); MessageBox(hWnd,buf,"Windows Sockets Error",MB_OK); shutdown_appl(); } . . /* HostBuffer now contains a host buffer, use info from it. */ . . }