分类: C/C++
2012-01-27 03:58:28
WSAEventSelect()函数和WSAAsyncSelect()函数类似,它们的区别在于当一个FD_XXX网络事件发生时,WSAEventSelect()函数将导致一个应用程序指定的事件对象将被设置,即将网络事件投递到一个事件对象句柄,而不是将网络事件(消息)投递至一个窗口句柄。
WSAEventSelect()函数原型如下:
以下为测试WSAEventSelect()函数的程序,一个服务器端两个客户端
下面是服务器端程序:
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 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /************************************************************************/ /* 事件对象I/O管理程序实例 */ /************************************************************************/ #include #pragma comment(lib,"ws2_32") #include int main() { printf("服务端程序\n"); //------①加载---------- WSADATA wsaData; if (WSAStartup(MAKEWORD(2,2),&wsaData)!=0) { printf("WSAStartup Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("①加载成功\n"); //-------②创建流式套接字------------ SOCKET s=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); if (s==INVALID_SOCKET) { printf("socket() Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("②已创建监听套接口:【%d】\n",s); //将套接口s置于”非阻塞模式“ u_long u1=1; ioctlsocket(s,FIONBIO,(u_long*)&u1); //-----------③绑定本地地址--------------------- struct sockaddr_in Sadd; Sadd.sin_family=AF_INET; Sadd.sin_port=htons(5555); Sadd.sin_addr.S_un.S_addr=inet_addr("192.168.31.1"); if (bind(s,(sockaddr*)&Sadd,sizeof(Sadd))==SOCKET_ERROR) { printf("bind() Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("③绑定成功,本地IP地址:【%s】,端口号:【%d】\n",inet_ntoa(Sadd.sin_addr),ntohs(Sadd.sin_port)); //--------------④进入监听状态----------------- if (listen(s,5)==SOCKET_ERROR) { printf("listen Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("④进入监听状态\n"); //--------------⑤创建事件对象----------------- WSAEVENT NewEvent=WSACreateEvent(); if (NewEvent==WSA_INVALID_EVENT) { printf("WSACreateEvent() Failed,Error=【%d】\n",WSAGetLastError()); return 1; } else printf("⑤创建一个事件对象,返回的事件对象句柄NewEvent=%d\n",NewEvent); //--------------⑥网络事件注册------------ int WESerror=WSAEventSelect(s,NewEvent,FD_ACCEPT|FD_CLOSE); if (WESerror==INVALID_SOCKET) { printf("WSAEventSelect() Failed,Error=【%d】\n",WSAGetLastError()); return -1; } else printf("⑥套接口【%d】、事件对象【%d】和网络事件FD_ACCEPT|FD_CLOSE已关联\n",s,NewEvent); //-----------准备工作--------------- int t=1; WSAEVENT eventArray[WSA_MAXIMUM_WAIT_EVENTS]; SOCKET sockArray[WSA_MAXIMUM_WAIT_EVENTS]; int n=0; eventArray[n]=NewEvent; sockArray[n]=s; n++; //------------循环处理------------- while (true) { //---------------⑦等待事件对象-------------- int nIndex=WSAWaitForMultipleEvents(n,eventArray,FALSE,40000,FALSE); printf("nIndex=%d\n",nIndex); if (nIndex==WSA_WAIT_FAILED)//------7.1调用失败--------- { printf("调用失败\n"); break; } else if (nIndex==WSA_WAIT_TIMEOUT)//-------7.2超时--------- { if (t<3) { printf("第【%d】次超时\n",t); t++; continue; } else { printf("第【%d】次超时,退出\n",t); break; } } //---------------7.3网络事件触发事件对象句柄的工作状态-------- else { WSANETWORKEVENTS event;//该结构记录网络事件和对应出错代码 //---------⑧网络事件查询----------- WSAEnumNetworkEvents(sockArray[nIndex-WSA_WAIT_EVENT_0],NULL,&event); WSAResetEvent(eventArray[nIndex-WSA_WAIT_EVENT_0]); if ((event.lNetworkEvents&FD_ACCEPT)!=0) //------8.1处理FD_ACCEPT通知消息 { if (event.iErrorCode[FD_ACCEPT_BIT]==0) { if (n>WSA_MAXIMUM_WAIT_EVENTS) { printf("Too many connections!\n"); break; } SOCKET sNew=accept(sockArray[nIndex-WSA_WAIT_EVENT_0],NULL,NULL); NewEvent=WSACreateEvent(); WSAEventSelect(sNew,NewEvent,FD_READ|FD_CLOSE); eventArray[n]=NewEvent; sockArray[n]=sNew; n++; } } else if (event.lNetworkEvents&FD_READ) //-------8.2处理FD_READ通知消息 { if (event.iErrorCode[FD_READ_BIT]==0) { char buf[256]; memset(buf,0,256); int nRecv=recv(sockArray[nIndex-WSA_WAIT_EVENT_0],buf,sizeof(buf),0); if (nRecv>0) { printf("接收到客户端【%d】数据:%s\n",sockArray[nIndex-WSA_WAIT_EVENT_0],buf); } } } else if (event.lNetworkEvents&FD_CLOSE) //---------8.3处理FD_CLOSE通知消息 { if (event.iErrorCode[FD_CLOSE_BIT]==0) { closesocket(sockArray[nIndex-WSA_WAIT_EVENT_0]); WSACloseEvent(eventArray[nIndex-WSA_WAIT_EVENT_0]); printf("套接字为【%d】的已关闭连接\n",sockArray[nIndex-WSA_WAIT_EVENT_0]); } else { if (event.iErrorCode[FD_CLOSE_BIT]==10053) { closesocket(sockArray[nIndex-WSA_WAIT_EVENT_0]); WSACloseEvent(eventArray[nIndex-WSA_WAIT_EVENT_0]); printf("客户端【%d】非法关闭连接\n",sockArray[nIndex-WSA_WAIT_EVENT_0]); } } for (int j=nIndex-WSA_WAIT_EVENT_0;j { sockArray[j]=sockArray[j+1]; eventArray[j]=eventArray[j+1]; } n--; } }// end 网络事件触发 }//end while printf("退出服务器程序\n"); closesocket(s); WSACleanup(); return 0; } |
客户端程序有两个,代码差不多,只是IP变了,这里给出一个,点击展开就可以看到
先启动服务器端,再启动1号客户端,接着启动2号客户端,就会看到如图所示: