2011-12-18 45 views
1

我试图通过WSAWaitForMulipleObjects获取FD_CLOSE事件(C++)。在WSASelectEvent中,我只设置了FD_CLOSE。但是,等待返回和网络激活也返回0,但NetworkEvents从激活状态返回0,所以我无法在其中看到FD_CLOSE。WSAWaitForMultipleEvents和NetworkEvents

任何帮助?

谢谢。

void EventThread(void* obj) 
{ 

    WSANETWORKEVENTS NetworkEvents; 

    WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS]; 
    DWORD EventTotal = 0; 
    EventArray[EventTotal] = WSACreateEvent(); 
    EventTotal++; 
    int res; 
    int index; 
    if(WSAEventSelect(_socket, EventArray[EventTotal - 1], FD_CLOSE)==SOCKET_ERROR) 
     Logger::GetInstance() << "WSAEventSelect failed with error " << WSAGetLastError() << endl; 

    bool bResult; 
    while(true) 
    { 
     if((index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE))==WSA_WAIT_FAILED) 
     { 
      Logger::GetInstance() << "WSAWaitForMultipleEvents failed with error " << WSAGetLastError() << endl; 
     } 


     if ((index != WSA_WAIT_FAILED) && (index != WSA_WAIT_TIMEOUT)) { 
      res = WSAEnumNetworkEvents(_socket, EventArray[index - WSA_WAIT_EVENT_0], &NetworkEvents) ; 

      if(NetworkEvents.lNetworkEvents & FD_CLOSE) 
      { 
       if(NetworkEvents.iErrorCode[FD_CLOSE_BIT] !=0) 
       { 
        Logger::GetInstance() << "FD_CLOSE failed with error " << NetworkEvents.iErrorCode[FD_CLOSE_BIT] << endl; 
       } 
       else 
       { 
        Logger::GetInstance() << "FD_CLOSE is OK!!! " << NetworkEvents.iErrorCode[FD_CLOSE_BIT] << endl; 
       } 
      } 
     } 


    } 

} 
+0

你做了什么来触发事件? (尽可能精确。) – 2011-12-18 09:53:10

+0

通过WSAEventSelect注册到FD_CLOSE,然后WSAWaitForMultipleEvents – gln 2011-12-18 09:57:57

+0

正确,但是您是如何触发事件的?这就是你等待事件的方式,但你是如何使事件发生的? – 2011-12-18 09:58:28

回答

1

WinSock documentation说以下内容:当接收 紧密指示对应于所述插座中的虚电路被张贴

FD_CLOSE消息。在TCP中, 这意味着FD_CLOSE在连接进入 ,TIME_WAITCLOSE_WAIT状态时发布。这是因为发送端的 远端执行shutdown()closesocket()FD_CLOSE只应在从套接字 读取所有数据后发布,但应用程序应在收到 FD_CLOSE时检查其余数据,以避免任何丢失数据的可能性。

要知道,应用程序将只收到FD_CLOSE消息 指示虚电路关闭,只有当所有的 接收到的数据已被读取,如果这是一个正常关闭。它不会 收到FD_READ消息来指示此情况。

...

这里是事件和条件的每个异步 通知消息的摘要。

...

FD_CLOSE:只有有效的面向连接的插座(例如, SOCK_STREAM)

  1. WSAAsyncSelect()调用,如果套接字连接已关闭。

  2. 后远程系统启动正常关闭,当目前没有收到(请注意数据,如果数据已收到 并正在等待在远程系统启动 正常关闭被读取时,FD_CLOSE不交付,直到读取所有未决数据 )。

  3. 本地系统之后发起正常关闭与shutdown()和远程系统已经响应了“结束数据的”通知( 例如,TCP FIN),当没有当前可用的数据要接收。

  4. 当远程系统终止连接(例如,发送TCP RST)时,lParam将包含WSAECONNRESET错误值。

注意FD_CLOSE不会在调用closesocket()后发布。

拉出网线并不满足这些条件。这实际上是通过设计来实现的,因为网络旨在处理意外中断,因此它们可以在短暂中断时尽可能保持现有连接。等待几分钟,直到操作系统超时,看看会发生什么。此外,当您重新接入电缆时,操作系统将验证预先存在的连接,然后可能会或可能不会重置它们。