Winsock2 AsyncSelect编程实例

#include #include #include #include #include #define PORT 5150 #define BUFFER_SIZE 8192 #define WM_SOCKET (WM_USER + 1) typedef struct _SOCKET_INFORMATION { BOOL bRecvPosted; CHAR Buffer[BUFFER_SIZE]; WSABUF wsaBuf; SOCKET Socket; DWORD dwBytesSend; DWORD dwBytesRecv; struct _SOCKET_INFORMATION *pNext; } SOCKET_INFORMATION, *LPSOCKET_INFORMATION; void CreateSocketInformation(SOCKET s); LPSOCKET_INFORMATION GetSocketInformation(SOCKET s); void FreeSocketInformation(SOCKET s); HWND MakeWorkerWindow(void); LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); LPSOCKET_INFORMATION SocketInfoList; void main(int argc, char ** argv) { MSG msg; int nRet; SOCKET Listen; SOCKADDR_IN sa; HWND hWnd; WSADATA wsaData; hWnd = MakeWorkerWindow(); if (NULL == hWnd) { return; } nRet = WSAStartup(MAKEWORD(2,2), &wsaData); if (nRet != 0) { printf("WSAStartup() failed with error: %d/n", nRet); return; } Listen = socket(AF_INET, SOCK_STREAM, 0); if (INVALID_SOCKET == Listen) { printf("socket() failed with error: %d/n", WSAGetLastError()); return; } WSAAsyncSelect(Listen, hWnd, WM_SOCKET, FD_ACCEPT | FD_CLOSE); memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_addr.s_addr = htonl(INADDR_ANY); sa.sin_port = htons(PORT); nRet = bind(Listen, (LPSOCKADDR)&sa, sizeof(sa)); if (SOCKET_ERROR == nRet) { printf("bind() failed with error: %d/n", WSAGetLastError()); return; } nRet = listen(Listen, 5); if (SOCKET_ERROR == nRet) { printf("listen() failed with error: %d/n", WSAGetLastError()); return; } //分发消息 while(nRet = GetMessage(&msg, NULL, 0, 0)) { if (-1 == nRet) { printf("GetMessage() failed with error: %d/n", GetLastError()); return; } TranslateMessage(&msg); DispatchMessage(&msg); } } LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { int nRet = 0; SOCKET Remote; LPSOCKET_INFORMATION SocketInfo; DWORD dwRecvBytes, dwSendBytes; DWORD dwFlags; if (WM_SOCKET == uMsg) { if (WSAGETSELECTERROR(lParam)) { printf("Socket failed with error: %d/n", WSAGETSELECTERROR(lParam)); FreeSocketInformation(wParam); } else { switch(WSAGETSELECTEVENT(lParam)) { case FD_ACCEPT: Remote = accept(wParam, NULL, NULL); if (INVALID_SOCKET == Remote) { printf("accept() failed with error: %d/n", WSAGetLastError()); break; } CreateSocketInformation(Remote); printf("Socket Number: %d connected!/n", Remote); WSAAsyncSelect(Remote, hWnd, WM_SOCKET, FD_READ | FD_WRITE | FD_CLOSE); break; case FD_READ: SocketInfo = GetSocketInformation(wParam); if (SocketInfo->dwBytesRecv != 0) { SocketInfo->bRecvPosted = TRUE; return 0; } else { SocketInfo->wsaBuf.buf = SocketInfo->Buffer; SocketInfo->wsaBuf.len = BUFFER_SIZE; dwFlags = 0; nRet = WSARecv(SocketInfo->Socket, &(SocketInfo->wsaBuf), 1, &dwRecvBytes, &dwFlags, NULL, NULL); if (SOCKET_ERROR == nRet) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSARecv() failed with error: %d/n", WSAGetLastError()); FreeSocketInformation(wParam); return 0; } } else { SocketInfo->dwBytesRecv = dwRecvBytes; } } //DO NOT BREAK HERE SINCE WE GOT A SUCCESSFUL RECV. //Go ahead and begin writing data to the client. case FD_WRITE: SocketInfo = GetSocketInformation(wParam); if (SocketInfo->dwBytesRecv > SocketInfo->dwBytesSend) { SocketInfo->wsaBuf.buf = SocketInfo->Buffer + SocketInfo->dwBytesSend; SocketInfo->wsaBuf.len = SocketInfo->dwBytesRecv - SocketInfo->dwBytesSend; nRet = WSASend(SocketInfo->Socket, &(SocketInfo->wsaBuf), 1, &dwSendBytes, 0, NULL, NULL); if (SOCKET_ERROR == nRet) { if (WSAGetLastError() != WSAEWOULDBLOCK) { printf("WSASend() failed with error: %d/n", WSAGetLastError()); FreeSocketInformation(wParam); return 0; } } else { SocketInfo->dwBytesSend += dwSendBytes; } } if (SocketInfo->dwBytesRecv == SocketInfo->dwBytesSend) { SocketInfo->dwBytesSend = 0; SocketInfo->dwBytesRecv = 0; if (TRUE == SocketInfo->bRecvPosted) { SocketInfo->bRecvPosted = FALSE; PostMessage(hWnd, WM_SOCKET, wParam, FD_READ); } } break; case FD_CLOSE: printf("Closing socket: %d/n", wParam); FreeSocketInformation(wParam); break; default: break; } } return 0; } return DefWindowProc(hWnd, uMsg, wParam, lParam); } void CreateSocketInformation(SOCKET s) { LPSOCKET_INFORMATION si; si = (LPSOCKET_INFORMATION)GlobalAlloc(GPTR, sizeof(SOCKET_INFORMATION)); if (NULL == si) { printf("GlobalAlloc() failed with error: %d/n", GetLastError()); return; } si->Socket = s; si->bRecvPosted = FALSE; si->dwBytesRecv = 0; si->dwBytesSend = 0; si->pNext = SocketInfoList; SocketInfoList = si; } LPSOCKET_INFORMATION GetSocketInformation(SOCKET s) { LPSOCKET_INFORMATION si = SocketInfoList; while(si) { if (si->Socket == s) { return si; } si = si->pNext; } return NULL; } void FreeSocketInformation(SOCKET s) { LPSOCKET_INFORMATION si = SocketInfoList; LPSOCKET_INFORMATION PrevSi = NULL; while(si) { if (s == si->Socket) { if (PrevSi) { PrevSi->pNext = si->pNext; } else { SocketInfoList = si->pNext; } closesocket(si->Socket); GlobalFree(si); return; } PrevSi = si; si = si->pNext; } } HWND MakeWorkerWindow(void) { WNDCLASS wndClass; CHAR *ProviderClass = "AsyncSelect"; HWND Window; wndClass.style = CS_HREDRAW | CS_VREDRAW; wndClass.lpfnWndProc = (WNDPROC)WindowProc; wndClass.cbClsExtra = 0; wndClass.cbWndExtra = 0; wndClass.hInstance = NULL; wndClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); wndClass.hCursor = LoadCursor(NULL, IDC_ARROW); wndClass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wndClass.lpszMenuName = NULL; wndClass.lpszClassName = ProviderClass; if (0 == RegisterClass(&wndClass)) { printf("RegisterClass() failed with error: %d/n", GetLastError()); return NULL; } Window = CreateWindow( ProviderClass, "", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, NULL, NULL); if (NULL == Window) { printf("CreateWindow() failed with error: %d/n", GetLastError()); return NULL; } return Window; }

你可能感兴趣的:(C/C++)