分类: C/C++
2012-01-27 03:59:29
WSAAsyncSelect( )是Winsock提供的一个适合于Windows编程使用的函数,它允许在一个套接口上当发生特定的网络事件时,给Windows网络应用程序(窗口或对话框)发送一个消息(事件通知)。
WSAAsyncSelect函数原型如下:
若应用程序对一个套接口s调用了WSAAsyncSelect( )函数,那么套接口s的模式会自动从阻塞模式变成非阻塞模式。如果应用程序同时对多个网络事件感兴趣,那么只需对各种类型的网络事件执行按位或(OR)的运算即可。进行一次WSAAsyncSelect( )调用,将使为同一个套接口启动的所有以前的WSAAsyncSelect( )调用作废。如果要取消所有的通知,也就是指出Windows Sockets的实现不再在套接口上发送任何和网络事件相关的消息,则把lEvent字段置为0,然后调用WSAAsyncSelect( )。当某一套接口s上发生了一个已命名的网络事件时,应用程序窗口hWnd会接收到消息wMsg。应用程序窗口例程的wParam参数标识了网络事件发生的套接口。lParam参数的低位字指明了发生的网络事件,高位字则含有一个错误代码,该错误代码可以是Winsock2.h中定义的任何错误。
以下为测试WSAAsyncSelect()函数的程序,一个服务器端两个客户端
下面是服务器端程序:
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 067 068 069 070 071 072 073 074 075 076 077 078 079 080 081 082 083 084 085 086 087 088 089 090 091 092 093 094 095 096 097 098 099 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 | #define WM_SOCKET WM_USER+101 #include /*#include #pragma comment(lib,"WS2_32") //----------------窗口过程函数的声明------------- LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam); //----------------WinMain()函数------------------ int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd ) { WNDCLASS wc; wc.style=CS_HREDRAW|CS_VREDRAW; wc.lpfnWndProc=WindowProc; wc.cbCl***tra=0; wc.cbWndExtra=0; wc.hInstance=hInstance; wc.hIcon=LoadIcon(NULL,IDI_EXCLAMATION); wc.hCursor=LoadCursor(NULL,IDC_ARROW); wc.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); wc.lpszMenuName=NULL; wc.lpszClassName="Test"; //---注册窗口类---- RegisterClass(&wc); //---创建窗口---- HWND hwnd=CreateWindow("Test","窗口标题",WS_SYSMENU,300,0,600,400,NULL,NULL,hInstance,NULL); if (hwnd==NULL) { MessageBox(hwnd,"创建窗口出错","标题栏提升",MB_OK); return 1; } //---显示窗口---- ShowWindow(hwnd,SW_SHOWNORMAL); UpdateWindow(hwnd); //---socket----- WSADATA wsaData; WORD wVersionRequested=MAKEWORD(2,2); if (WSAStartup(wVersionRequested,&wsaData)!=0) { MessageBox(NULL,"WSAStartup() Failed","调用失败",0); return 1; } SOCKET s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (s==INVALID_SOCKET) { MessageBox(NULL,"socket() Failed","调用失败",0); return 1; } sockaddr_in sin; sin.sin_family=AF_INET; sin.sin_port=htons(1111); sin.sin_addr.S_un.S_addr=inet_addr("192.168.31.1"); if (bind(s,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR) { MessageBox(NULL,"bind() Failed","调用失败",0); return 1; } if (listen(s,3)==SOCKET_ERROR) { MessageBox(NULL,"listen() Failed","调用失败",0); return 1; } else MessageBox(hwnd,"进入监听状态!","标题栏提示",MB_OK); WSAAsyncSelect(s,hwnd,WM_SOCKET,FD_ACCEPT|FD_CLOSE); //---消息循环---- MSG msg; while (GetMessage(&msg,0,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } closesocket(s); WSACleanup(); return msg.wParam; } //-------------------窗口过程---------------------- LRESULT CALLBACK WindowProc(HWND hwnd,UINT uMsg,WPARAM wParam,LPARAM lParam) { switch(uMsg) { case WM_SOCKET: { SOCKET ss=wParam; //wParam参数标志了网络事件发生的套接口 if (WSAGETSELECTERROR(lParam)) { closesocket(ss); return 0; } switch (WSAGETSELECTEVENT(lParam)) { case FD_ACCEPT: //-----①连接请求到来 { sockaddr_in Cadd; int Cadd_len=sizeof(Cadd); SOCKET sNew=accept(ss,(sockaddr*)&Cadd,&Cadd_len); if (ss==INVALID_SOCKET) MessageBox(hwnd,"调用accept()失败!","标题栏提示",MB_OK); WSAAsyncSelect(sNew,hwnd,WM_SOCKET,FD_READ|FD_CLOSE); }break; case FD_READ: //-----②数据发送来 { char cbuf[256]; memset(cbuf,0,256); int cRecv=recv(ss,cbuf,256,0); if ((cRecv==SOCKET_ERROR&& WSAGetLastError() == WSAECONNRESET)|| cRecv==0) { MessageBox(hwnd,"调用recv()失败!","标题栏提示",MB_OK); closesocket(ss); } else if (cRecv>0) { MessageBox(hwnd,cbuf,"收到的信息",MB_OK); char Sbuf[]="Hello client!I am server"; int isend=send(ss,Sbuf,sizeof(Sbuf),0); if (isend==SOCKET_ERROR || isend<=0) { MessageBox(hwnd,"发送消息失败!","标题栏提示",MB_OK); } else MessageBox(hwnd,"已经发信息到客户端!","标题栏提示",MB_OK); } }break; case FD_CLOSE: //----③关闭连接 { closesocket(ss); } break; } } break; case WM_CLOSE: if (IDYES==MessageBox(hwnd,"是否确定退出?","message",MB_YESNO)) DestroyWindow(hwnd); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hwnd,uMsg,wParam,lParam); } return 0; } |
先启动服务器端,再启动1号客户端,接着启动2号客户端,就会看到如图所示: