WSAAsyncSelect model
Winsock provides a useful asynchronous Ihampar O model. Using this model, applications can receive network event notifications based on Windows messages on a socket. The specific way to do this is to call the WSAAsyncSelect function after building a socket. The model first appeared in version 1.1 of Winsock to help application developers adapt to their "backward" multitasking messaging environment for some early 16-bit Windows platforms such as Windows for Workgroups. Applications can still benefit from this model, especially if they use a standard Windows routine (often called "WndProc") to manage window messages. The model has also been adopted by the Microsoft Foundation Class (Microsoft basic Class, MFC) object CSocket.
# include # include # define PORT 5150 # define MSGSIZE 1024 # define WM_SOCKET WM_USER+0 # pragma comment (lib, "ws2_32.lib") LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow) {static TCHAR szAppName [] = _ T ("AsyncSelect Model"); HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW Wndclass.lpfnWndProc = WndProc; wndclass.cbClsExtra = 0; wndclass.cbWndExtra = 0; wndclass.hInstance = hInstance; wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW); wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH); wndclass.lpszMenuName = NULL; wndclass.lpszClassName = szAppName If (! RegisterClass & wndclass) {MessageBox (NULL, TEXT ("This program requires Windows NT!"), szAppName, MB_ICONERROR); return 0 } hwnd = CreateWindow (szAppName, / / window class name TEXT ("AsyncSelect Model"), / / window caption WS_OVERLAPPEDWINDOW, / / window style CW_USEDEFAULT, / / initial x position CW_USEDEFAULT / / initial y position CW_USEDEFAULT, / / initial x size CW_USEDEFAULT, / / initial y size NULL, / / parent window handle NULL / / window menu handle hInstance, / / program instance handle NULL) / / creation parameters ShowWindow (hwnd, iCmdShow); UpdateWindow (hwnd); while (GetMessage (& msg, NULL, 0,0)) / / get message {TranslateMessage (& msg); / / convert keyboard information DispatchMessage (& msg); / / send the message to the specified form} return msg.wParam;} LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) {WSADATA wsd Static SOCKET sListen; SOCKET sClient; SOCKADDR_IN local, client; int ret, iAddrSize = sizeof (client); char szMessage [MSGSIZE]; switch (message) {case WM_CREATE: / / Initialize Windows Socket library WSAStartup (0x0202, & wsd); / / Create listening socket sListen = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP) / / Bind local.sin_addr.S_un.S_addr = htonl (INADDR_ANY); local.sin_family = AF_INET; local.sin_port = htons (PORT); bind (sListen, (struct sockaddr *) & local, sizeof (local)); / / Listen listen (sListen, 3); / / Associate listening socket with FD_ACCEPT event WSAAsyncSelect (sListen, hwnd, WM_SOCKET, FD_ACCEPT); return 0 Case WM_DESTROY: closesocket (sListen); WSACleanup (); PostQuitMessage (0); return 0; case WM_SOCKET: if (WSAGETSELECTERROR (lParam)) {closesocket (wParam); break } switch (WSAGETSELECTEVENT (lParam)) {case FD_ACCEPT: / / Accept a connection from client sClient = accept (wParam, (struct sockaddr *) & client, & iAddrSize); / / Associate client socket with FD_READ and FD_CLOSE event WSAAsyncSelect (sClient, hwnd, WM_SOCKET, FD_READ | FD_CLOSE); break Case FD_READ: ret = recv (wParam, szMessage, MSGSIZE, 0); if (ret = = 0 | | ret = = SOCKET_ERROR & & WSAGetLastError () = = WSAECONNRESET) {closesocket (wParam);} else {szMessage [ret] ='\ 0mm; send (wParam, szMessage, strlen (szMessage), 0);} break Case FD_CLOSE: closesocket (wParam); break;} return 0;} / give the information we don't process to the system for default processing return DefWindowProc (hwnd, message, wParam, lParam);}
In my opinion, WSAAsyncSelect is the simplest type of Winsock I-amp O model (it's simple because a main thread is done). Anyone who has written window-like applications using Raw Windows API should be able to read it. Here, all we need to do is:
1. In the WM_CREATE message handling function, initialize Windows Socket library, create a listening socket, bind, listen, and call the WSAAsyncSelect function to indicate that we are concerned about the FD_ACCEPT event that occurs on the listening socket
two。 Customize a message WM_SOCKET. Once an event occurs on the sockets we care about (listening sockets and client sockets), the system calls WndProc and the message parameter is set to WM_SOCKET.
3. In the message handling function of WM_SOCKET, FD_ACCEPT, FD_READ and FD_CLOSE events are handled respectively.
4. In the window destroy message (WM_DESTROY) handler, we turn off the listening socket and clear the Windows Socket library
The following table of network event types for the WSAAsyncSelect function gives you a better understanding of each network event:
Table 1
FD_READ
The application wants to receive notifications about whether it is readable in order to read in the data
FD_WRITE
The application wants to receive notifications about whether it is writable or not in order to write data
FD_OOB
The application wants to receive notification of the arrival of out-of-band (OOB) data
FD_ACCEPT
The application wants to receive notifications about entering the connection
FD_CONNECT
The application wants to receive notification of the completion of a single connection or multipoint join operation
FD_CLOSE
The application wants to receive notifications related to socket shutdown
FD_QOS
The application wants to receive notification that the socket "quality of service" (QoS) has changed
FD_GROUP_QOS
The application wants to receive notification of a change in the socket group "quality of service" (it is not useful now, reserved for future use of socket groups)
FD_ROUTING_INTERFACE_CHANGE
The application wants to receive notification of a change in the routing interface in the specified direction
FD_ADDRESS_LIST_CHANGE
The application wants to receive notification of a change in the local address list for the protocol family of sockets