windows - WSAEventSelect,零事件

标签 windows winapi sockets winsock

在我的套接字服务器中,我使用 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(;;) 循环都会执行两次。或者,在检测到 FD_ACCEPT 后,WSAEnumNetworkEvents 可能不会重置 sockEv。

这个零事件意味着什么以及为什么会发生? 我在文档中没有找到任何相关信息。

更新:可编译示例

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 32 位上尝试了此代码。

最佳答案

回答我自己的问题。看来我找到了发生这种情况的原因和时间。这个零事件发生在客户端套接字(accept()返回的套接字)关闭之后。如果您不将 FD_CLOSE 与 WSAEventSelect 一起使用,则不会发生这种情况。所以人们可以忽略它。 MSDN 没有提及这种行为。

关于windows - WSAEventSelect,零事件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12268811/

相关文章:

C 执行命令窗口

php - 错误 0x2006D002 :BIO routines:BIO_new_file:system lib with PHP on Windows

c++ - 当前路径的 loadlibrary 失败,GetLastError() == 0

c++ - 相对路径问题 - 一个 dir up

c - 在 c 中制作和发送混合 double 和整数数组

Android Lollipop (5.1.1) - 创建套接字连接时如何使用 IPV6 地址

java - 在 Eclipse 中进行 JUnit 测试之前运行外部命令

c++ - 来自 32 位进程的 64 位注册表项的 SetNamedSecurityInfo

javascript - 加载源为 : (socketio) 的 <script> 失败

c++ - 如何驯服 Windows header (有用的定义)?