WSAEventSelect,零事件

在我的套接字服务器中,我使用WSAEventSelect()和WSAEnumNetworkEvents()来检测FD_ACCEPT和FD_CLOSE事件。

这里是我的代码的简化版本:

HANDLE sockEv=CreateEvent(NULL,TRUE,FALSE,NULL); WSAEventSelect(servSocket,sockEv,FD_ACCEPT|FD_CLOSE); for(;;) { if(WSAWaitForMultipleEvents(1,&sockEv,FALSE,INFINITE,FALSE)==WSA_WAIT_EVENT_0) { WSANETWORKEVENTS wsaEvents={0}; WSAEnumNetworkEvents(servSocket,sockEv,&wsaEvents); if((wsaEvents.lNetworkEvents & FD_ACCEPT)==FD_ACCEPT) { SOCKET clntSock=accept(servSocket,(sockaddr*)clientAddr,&addrlen); .... } else if (wsaEvents.lNetworkEvents==0) { // this event occurs after each FD_ACCEPT event } .... } .... } 

问题是,每次从客户端接受新连接时,都会收到2个事件:首先将WSANETWORKEVENTS.lNetworkEvents设置为FD_ACCEP,然后将WSANETWORKEVENTS.lNetworkEvents设置为零。 这就是for(;;)循环每次接受一个新的客户时执行2次。 或者可能在检测到FD_ACCEPT之后,WSAEnumNetworkEvents不会重置sockEv。

这个零事件是什么意思,为什么会发生? 我没有在文档中find任何有关它的信息。

更新 :可编译的样本

 int _tmain(int argc, _TCHAR* argv[]) { WSADATA wsaData; WSAStartup(MAKEWORD(2,2),&wsaData); try { SOCKET servSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); sockaddr_in serv={0}; serv.sin_family=AF_INET; serv.sin_addr.s_addr=htonl(INADDR_ANY); serv.sin_port=htons(18081); memset(serv.sin_zero,0,sizeof(serv.sin_zero)); if(bind(servSocket,(sockaddr*)&serv,sizeof(serv))==SOCKET_ERROR) throw WSAGetLastError(); if(listen(servSocket,SOMAXCONN)==SOCKET_ERROR) throw WSAGetLastError(); HANDLE sockEv=CreateEvent(NULL,TRUE,FALSE,NULL); if(WSAEventSelect(servSocket,sockEv,FD_ACCEPT|FD_CLOSE)==SOCKET_ERROR) throw WSAGetLastError(); for(;;) { if(WSAWaitForMultipleEvents(1,&sockEv,FALSE,INFINITE,FALSE)!=WSA_WAIT_EVENT_0) throw -1; WSANETWORKEVENTS wsaEvents={0}; if(WSAEnumNetworkEvents(servSocket,sockEv,&wsaEvents)==SOCKET_ERROR) throw WSAGetLastError(); if((wsaEvents.lNetworkEvents & FD_ACCEPT)==FD_ACCEPT) { SOCKET clntSocket=accept(servSocket,0,0); closesocket(clntSocket); puts("accept"); } else if(wsaEvents.lNetworkEvents==0) { puts("zero event"); } } } catch(int errorCode) { printf("Last Error: %d\n",errorCode); } WSACleanup(); return 0; } 

我在WinXP 32bit上试过这个代码。

回答我自己的问题。 看来我发现了为什么和何时发生这种情况。 这个零事件在客户端套接字(由accept()返回的套接字)关闭之后发生。 如果您不使用FD_CLOSE和WSAEventSelect,则不会发生这种情况。 所以人们可以忽略它。 MSDN对此行为一无所知。