《Windows网络与通信程序设计》读书笔记-----WSAAsyncSelect模型

来源:互联网 发布:线切割软件编程 编辑:程序博客网 时间:2024/05/22 12:08

WSAAsyncSelect模型

WSAAsyncSelect模型允许应用程序以Windows消息的接收网络事件通知。这个模型是为了适应Windows的消息驱动环境而设置的,现在许多对性能要求不高的网络应用程序都采用WSAAsyncSelect模型,MFC中的CSocket类也使用了它。

 

WSAAsyncSelect函数自动把套接字设为非阻塞模式,并且为套接字绑定一个窗口句柄和发送哪些通知码(FD_READ之类的)。当有网络事件发生时,便向这个窗口发送程序自定义的消息。


具体编程流程

1、         自定义一个与网络通知消息,用于通知WSAsyncSelect绑定中的窗口。

2、         创建一个窗口,用于WSAAsyncSelect绑定到指定的套接字。

3、         编写上述窗口的消息处理函数。在收到自定义网络通知消息后,提取出相应错误码和网络事(FD_ACCEPT、       FD_READ、FD_WRIET、FD_CLOSE),并作出相应的处理。


#define _WIN32_WINNT 0x0400   #include<windows.h>#include<cstdio>#include"InitSocket.h"//需要自定义一个消息#define WM_SOCKET WM_USER+1CInitSock initSock ; //进入main函数前已经进行了初始化LONG CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) ;int main(void){char szClassName[] = "MainWClass" ;WNDCLASSEX wndclass ;wndclass.cbSize = sizeof(wndclass) ;wndclass.style = CS_HREDRAW|CS_VREDRAW ;wndclass.lpfnWndProc = 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 = szClassName ;wndclass.hIconSm = NULL ;RegisterClassEx(&wndclass) ;//创建主窗口HWND hWnd = CreateWindowEx(0,szClassName,"",WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,NULL,NULL ) ;if(NULL == hWnd){MessageBox(NULL,"创建窗口出错!","error",MB_OK) ;return -1 ;} USHORT nPort = 4567 ;SOCKET sListen = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP) ;sockaddr_in sin ;sin.sin_family = AF_INET ;sin.sin_port = htons(nPort) ;sin.sin_addr.s_addr = INADDR_ANY ;if(bind(sListen,(sockaddr*)&sin,sizeof(sin)) == SOCKET_ERROR){printf("Failed bind()\n") ;return -1 ;}//将套接字设为窗口通知消息类型,自动将套接字设置为非阻塞模式WSAAsyncSelect(sListen,hWnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE) ;listen(sListen,5) ;MSG msg ;while(GetMessage(&msg,NULL,0,0)){TranslateMessage(&msg) ;DispatchMessage(&msg) ;}return msg.wParam ;}LONG CALLBACK WindowProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam) {switch(uMsg){case WM_SOCKET :{SOCKET s = wParam ;if(WSAGETSELECTERROR(lParam)){closesocket(s) ;return 0 ;}switch(WSAGETSELECTEVENT(lParam)){case FD_ACCEPT :{SOCKET client = accept(s,NULL,NULL) ;WSAAsyncSelect(client,hWnd,WM_SOCKET,FD_READ|FD_WRITE|FD_CLOSE) ;printf("接收一个连接\n") ;}break ;case FD_WRITE:break ;case FD_READ :{char szText[1024] =  {0} ;if(recv(s,szText,1024,0) == SOCKET_ERROR){closesocket(s) ;}else{printf("接收数据:%s",szText) ;}break ;}case FD_CLOSE :{printf("关闭一个连接\n") ;closesocket(s);}break ;}return 0 ;}case WM_DESTROY :PostQuitMessage(0) ;return 0 ;}//将我们不处理的消息交给系统做默认处理return DefWindowProc(hWnd,uMsg,wParam,lParam) ;}