WSAEnumNetworkEvents 函数 (winsock2.h)

WSAEnumNetworkEvents 函数可发现所指示套接字的网络事件、清除内部网络事件记录以及重置事件对象 (可选) 。

语法

int WSAAPI WSAEnumNetworkEvents(
  [in]  SOCKET             s,
  [in]  WSAEVENT           hEventObject,
  [out] LPWSANETWORKEVENTS lpNetworkEvents
);

参数

[in] s

标识套接字的描述符。

[in] hEventObject

标识要重置的关联事件对象的可选句柄。

[out] lpNetworkEvents

指向 WSANETWORKEVENTS 结构的指针,该结构填充了发生的网络事件记录和任何关联的错误代码。

返回值

如果操作成功,则返回值为零。 否则,将返回值SOCKET_ERROR,并且可以通过调用 WSAGetLastError 检索特定的错误号。

错误代码 含义
WSANOTINITIALIZED
在使用此函数之前,必须成功调用 WSAStartup
WSAENETDOWN
网络子系统发生故障。
WSAEINVAL
指定的参数之一无效。
WSAEINPROGRESS
阻止 Windows 套接字 1.1 调用正在进行,或者服务提供商仍在处理回调函数。
WSAENOTSOCK
:描述符不是套接字。
WSAEFAULT
lpNetworkEvents 参数不是用户地址空间的有效部分。

注解

WSAEnumNetworkEvents 函数用于发现自上次调用此函数以来,指示的套接字发生了哪些网络事件。 它旨在与 WSAEventSelect 结合使用,后者将事件对象与一个或多个网络事件相关联。 当使用非零 lNetworkEvents 参数调用 WSAEventSelect 时,网络事件的记录将开始,并一直有效,直到将 lNetworkEvents 参数设置为零对 WSAEventSelect 进行另一次调用,或者直到调用 WSAAsyncSelect 为止。

WSAEnumNetworkEvents 仅报告通过 WSAEventSelect 指定的网络活动和错误。 请参阅 selectWSAAsyncSelect 的说明,了解这些函数如何报告网络活动和错误。

套接字的网络事件内部记录将复制到 lpNetworkEvents 引用的结构,然后清除内部网络事件记录。 如果 hEventObject 参数不是 NULL,则指示的事件对象也会重置。 Windows 套接字提供程序保证复制网络事件记录、清除网络事件记录和重置任何关联事件对象的操作都是原子的,因此,指定网络事件的下一次出现将导致事件对象设置。 如果此函数返回SOCKET_ERROR,则不会重置关联的事件对象,也不会清除网络事件的记录。

WSANETWORKEVENTS 结构的 lNetworkEvents 成员指示发生了哪些FD_XXX网络事件。 iErrorCode 数组用于包含与 lNetworkEvents 中事件位位置对应的数组索引的任何关联的错误代码。 FD_READ_BIT和FD_WRITE_BIT等标识符可用于为 iErrorCode 数组编制索引。 请注意,仅设置 iErrorCode 数组的那些元素,这些元素对应于 lNetworkEvents 参数中设置的位。 其他参数不会修改 (这对于与不知道新FD_ROUTING_INTERFACE_CHANGE的应用程序和FD_ADDRESS_LIST_CHANGE事件) 向后兼容非常重要。

可以返回以下错误代码以及相应的网络事件。

事件:FD_CONNECT

错误代码 含义
WSAEAFNOSUPPORT 指定系列中的地址无法与此套接字一起使用。
WSAECONNREFUSED 尝试连接被强制性拒绝。
WSAENETUNREACH 此时不可以从此主机访问该网络。
WSAENOBUFS 未提供任何缓冲区空间。 无法连接套接字。
WSAETIMEDOUT 尝试连接超时,但未建立连接
 

事件:FD_CLOSE

错误代码 含义
WSAENETDOWN 网络子系统发生故障。
WSAECONNRESET :此连接已由远端重置。
WSAECONNABORTED 由于超时或其他故障,连接已终止。
 

事件:FD_ACCEPT

事件:FD_ADDRESS_LIST_CHANGE

事件:FD_GROUP_QOS

事件:FD_QOS

事件:FD_OOB

事件:FD_READ

事件:FD_WRITE

错误代码 含义
WSAENETDOWN 网络子系统发生故障。
 

事件:FD_ROUTING_INTERFACE_CHANGE

错误代码 含义
WSAENETUNREACH 指定的目标不再可访问。
WSAENETDOWN 网络子系统发生故障。
 

示例代码

以下示例演示如何使用 WSAEnumNetworkEvents 函数。
#ifndef UNICODE
#define UNICODE
#endif

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#include <winsock2.h>
#include <Ws2tcpip.h>
#include <stdio.h>

// Link with ws2_32.lib
#pragma comment(lib, "Ws2_32.lib")

int main()
{
//-------------------------
// Declare and initialize variables
    WSADATA wsaData;
    int iResult;

    SOCKET SocketArray[WSA_MAXIMUM_WAIT_EVENTS], ListenSocket;
    WSAEVENT EventArray[WSA_MAXIMUM_WAIT_EVENTS];
    WSANETWORKEVENTS NetworkEvents;
    sockaddr_in InetAddr;
    DWORD EventTotal = 0;
    DWORD Index;
    DWORD i;
    
    HANDLE NewEvent = NULL; 

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
    if (iResult != 0) {
        wprintf(L"WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

//-------------------------
// Create a listening socket
    ListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (ListenSocket == INVALID_SOCKET) {
        wprintf(L"socket function failed with error: %d\n", WSAGetLastError() );
        return 1;
    }
    
    InetAddr.sin_family = AF_INET;
    InetAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    InetAddr.sin_port = htons(27015);

//-------------------------
// Bind the listening socket
    iResult = bind(ListenSocket, (SOCKADDR *) & InetAddr, sizeof (InetAddr));
    if (iResult != 0) {
        wprintf(L"bind failed with error: %d\n", WSAGetLastError() );
        return 1;
    }

//-------------------------
// Create a new event
    NewEvent = WSACreateEvent();
    if (NewEvent == NULL) {
        wprintf(L"WSACreateEvent failed with error: %d\n", GetLastError() );
        return 1;
    }    

//-------------------------
// Associate event types FD_ACCEPT and FD_CLOSE
// with the listening socket and NewEvent
    iResult = WSAEventSelect(ListenSocket, NewEvent, FD_ACCEPT | FD_CLOSE);
    if (iResult != 0) {
        wprintf(L"WSAEventSelect failed with error: %d\n", WSAGetLastError() );
        return 1;
    }

//-------------------------
// Start listening on the socket
    iResult = listen(ListenSocket, 10);
    if (iResult != 0) {
        wprintf(L"listen failed with error: %d\n", WSAGetLastError() );
        return 1;
    }

//-------------------------
// Add the socket and event to the arrays, increment number of events
    SocketArray[EventTotal] = ListenSocket;
    EventArray[EventTotal] = NewEvent;
    EventTotal++;

//-------------------------
// Wait for network events on all sockets
    Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);
    Index = Index - WSA_WAIT_EVENT_0;

//-------------------------
// Iterate through all events and enumerate
// if the wait does not fail.
    for (i = Index; i < EventTotal; i++) {
        Index = WSAWaitForMultipleEvents(1, &EventArray[i], TRUE, 1000, FALSE);
        if ((Index != WSA_WAIT_FAILED) && (Index != WSA_WAIT_TIMEOUT)) {
            WSAEnumNetworkEvents(SocketArray[i], EventArray[i], &NetworkEvents);
        }
    }

//...
    return 0;


Windows Phone 8:Windows Phone 8 及更高版本上的 Windows Phone 应用商店应用支持此函数。

Windows 8.1Windows Server 2012 R2:Windows 8.1、Windows Server 2012 R2 及更高版本的 Windows 应用商店应用支持此函数。

要求

要求
最低受支持的客户端 Windows 8.1,Windows Vista [桌面应用 |UWP 应用]
最低受支持的服务器 Windows Server 2003 [桌面应用 | UWP 应用]
目标平台 Windows
标头 winsock2.h
Library Ws2_32.lib
DLL Ws2_32.dll

另请参阅

WSAEventSelect

Winsock 函数

Winsock 参考