WSAEnumProtocolsA 函数 (winsock2.h)

WSAEnumProtocols 函数检索有关可用传输协议的信息。

语法

int WSAAPI WSAEnumProtocolsA(
  [in]      LPINT               lpiProtocols,
  [out]     LPWSAPROTOCOL_INFOA lpProtocolBuffer,
  [in, out] LPDWORD             lpdwBufferLength
);

参数

[in] lpiProtocols

NULL终止的 iProtocol 值的数组。 此参数是可选的;如果 lpiProtocolsNULL,则返回所有可用协议的信息。 否则,仅检索数组中列出的这些协议的信息。

[out] lpProtocolBuffer

指向用 WSAPROTOCOL_INFO 结构填充的缓冲区的指针。

[in, out] lpdwBufferLength

在输入时,传递给 WSAEnumProtocolslpProtocolBuffer 缓冲区中的字节数。 在输出中,可以传递给 WSAEnumProtocols 的最小缓冲区大小 以检索所有请求的信息。 此例程无法枚举多个调用;传入缓冲区必须足够大,才能容纳所有条目,以便例程成功。 这减少了 API 的复杂性,不应造成问题,因为计算机上加载的协议数通常很小。

返回值

如果未发生错误,WSAEnumProtocols 将返回要报告的协议数。 否则,返回SOCKET_ERROR值,并通过调用 WSAGetLastError来检索特定的错误代码。

错误代码 意义
WSANOTINITIALIZED
在使用此函数之前,必须成功 WSAStartup 调用。
WSAENETDOWN
网络子系统已失败。
WSAEINPROGRESS
正在进行阻止的 Windows 套接字 1.1 调用。
WSAEINVAL
指示指定参数之一无效。
WSAENOBUFS
缓冲区长度太小,无法接收所有相关 WSAPROTOCOL_INFO 结构和相关信息。 传入缓冲区至少与在 lpdwBufferLength中返回的值一样大。
WSAEFAULT
lpiProtocolslpProtocolBufferlpdwBufferLength 参数不是用户地址空间的有效部分。

言论

WSAEnumProtocols 函数用于发现有关本地计算机上安装的传输协议集合的信息。 分层协议仅在协议链中安装时可供应用程序使用。 除了在 lpProtocolBuffer中安装了链长度为零的虚拟分层服务提供商(LSP),不返回有关分层协议的信息。

注释 分层服务提供商已弃用。 从 Windows 8 和 Windows Server 2012 开始,请使用 Windows 筛选平台
 
lpiProtocols 参数可用作筛选器来限制提供的信息量。 通常,lpiProtocols 将指定为 NULL 指针,该指针将导致函数返回有关所有可用传输协议和协议链的信息。

WSAEnumProtocols 函数不同于 WSCEnumProtocolsWSCEnumProtocols32 函数,WSAEnumProtocols 函数不会为所有已安装的协议返回 WSAPROTOCOL_INFO 结构。 WSAEnumProtocols 函数排除服务提供商在 dwProviderFlagsWSAPROTOCOL_INFO 成员中设置的 PFL_HIDDEN 标志的协议,以向 Ws2_32.dll 指示不应在 WSAEnumProtocols 函数生成的结果缓冲区中返回此协议。 此外,WSAEnumProtocols 函数不会返回具有一个或多个链长度(LSP 提供程序)的 WSAPROTOCOL_INFO 结构的数据。 WSAEnumProtocols 仅返回缺少 PFL_HIDDEN 标志且没有协议链长度为零的基本协议和协议链的信息。

每个请求的协议 lpProtocolBuffer 指向的缓冲区中提供了 WSAPROTOCOL_INFO 结构。 如果指定的缓冲区不够大(由 lpdwBufferLength 的输入值指示),则会更新由 lpdwBufferLength 指向的值,以指示所需的缓冲区大小。 然后,应用程序应获取足够大的缓冲区,并再次调用 WSAEnumProtocols

缓冲区中出现 WSAPROTOCOL_INFO 结构的顺序与服务提供商使用 WS2_32.DLL 注册协议条目的顺序相吻合,或者通过为建立默认 TCP/IP 提供程序而提供的 Windows 套接字应用程序或 DLL 进行的任何后续重新排序。

Windows Phone 8: Windows Phone 8 及更高版本的 Windows Phone 应用商店应用支持 WSAEnumProtocolsW 功能。

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

例子

以下示例演示如何使用 WSAEnumProtocols 函数检索可用传输协议的 WSAPROTOCOL_INFO 结构数组。

#ifndef UNICODE
#define UNICODE 1
#endif

#include <winsock2.h>
#include <ws2tcpip.h>
#include <objbase.h>
#include <stdio.h>

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

#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
// Note: could also use malloc() and free()

int wmain()
{

    //-----------------------------------------
    // Declare and initialize variables
    WSADATA wsaData;
    int iResult = 0;

    int iError = 0;
    INT iNuminfo = 0;

    int i;

    // Allocate a 16K buffer to retrieve all the protocol providers
    DWORD dwBufferLen = 16384;

    LPWSAPROTOCOL_INFO lpProtocolInfo = NULL;

    // variables needed for converting provider GUID to a string
    int iRet = 0;
    WCHAR GuidString[40] = { 0 };

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

    lpProtocolInfo = (LPWSAPROTOCOL_INFO) MALLOC(dwBufferLen);
    if (lpProtocolInfo == NULL) {
        wprintf(L"Memory allocation for providers buffer failed\n");
        WSACleanup();
        return 1;
    }

    iNuminfo = WSAEnumProtocols(NULL, lpProtocolInfo, &dwBufferLen);
    if (iNuminfo == SOCKET_ERROR) {
        iError = WSAGetLastError();
        if (iError != WSAENOBUFS) {
            wprintf(L"WSAEnumProtocols failed with error: %d\n", iError);
            if (lpProtocolInfo) {
                FREE(lpProtocolInfo);
                lpProtocolInfo = NULL;
            }
            WSACleanup();
            return 1;
        } else {
            wprintf(L"WSAEnumProtocols failed with error: WSAENOBUFS (%d)\n",
                    iError);
            wprintf(L"  Increasing buffer size to %d\n\n", dwBufferLen);
            if (lpProtocolInfo) {
                FREE(lpProtocolInfo);
                lpProtocolInfo = NULL;
            }
            lpProtocolInfo = (LPWSAPROTOCOL_INFO) MALLOC(dwBufferLen);
            if (lpProtocolInfo == NULL) {
                wprintf(L"Memory allocation increase for buffer failed\n");
                WSACleanup();
                return 1;
            }
            iNuminfo = WSAEnumProtocols(NULL, lpProtocolInfo, &dwBufferLen);
            if (iNuminfo == SOCKET_ERROR) {
                iError = WSAGetLastError();
                wprintf(L"WSAEnumProtocols failed with error: %d\n", iError);
                if (lpProtocolInfo) {
                    FREE(lpProtocolInfo);
                    lpProtocolInfo = NULL;
                }
                WSACleanup();
                return 1;
            }

        }
    }

    wprintf(L"WSAEnumProtocols succeeded with protocol count = %d\n\n",
            iNuminfo);
    for (i = 0; i < iNuminfo; i++) {
        wprintf(L"Winsock Catalog Provider Entry #%d\n", i);
        wprintf
            (L"----------------------------------------------------------\n");
        wprintf(L"Entry type:\t\t\t ");
        if (lpProtocolInfo[i].ProtocolChain.ChainLen == 1)
            wprintf(L"Base Service Provider\n");
        else
            wprintf(L"Layered Chain Entry\n");

        wprintf(L"Protocol:\t\t\t %ws\n", lpProtocolInfo[i].szProtocol);

        iRet =
            StringFromGUID2(lpProtocolInfo[i].ProviderId,
                            (LPOLESTR) & GuidString, 39);
        if (iRet == 0)
            wprintf(L"StringFromGUID2 failed\n");
        else
            wprintf(L"Provider ID:\t\t\t %ws\n", GuidString);

        wprintf(L"Catalog Entry ID:\t\t %u\n",
                lpProtocolInfo[i].dwCatalogEntryId);

        wprintf(L"Version:\t\t\t %d\n", lpProtocolInfo[i].iVersion);

        wprintf(L"Address Family:\t\t\t %d\n",
                lpProtocolInfo[i].iAddressFamily);
        wprintf(L"Max Socket Address Length:\t %d\n",
                lpProtocolInfo[i].iMaxSockAddr);
        wprintf(L"Min Socket Address Length:\t %d\n",
                lpProtocolInfo[i].iMinSockAddr);

        wprintf(L"Socket Type:\t\t\t %d\n", lpProtocolInfo[i].iSocketType);
        wprintf(L"Socket Protocol:\t\t %d\n", lpProtocolInfo[i].iProtocol);
        wprintf(L"Socket Protocol Max Offset:\t %d\n",
                lpProtocolInfo[i].iProtocolMaxOffset);

        wprintf(L"Network Byte Order:\t\t %d\n",
                lpProtocolInfo[i].iNetworkByteOrder);
        wprintf(L"Security Scheme:\t\t %d\n",
                lpProtocolInfo[i].iSecurityScheme);
        wprintf(L"Max Message Size:\t\t %u\n", lpProtocolInfo[i].dwMessageSize);

        wprintf(L"ServiceFlags1:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwServiceFlags1);
        wprintf(L"ServiceFlags2:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwServiceFlags2);
        wprintf(L"ServiceFlags3:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwServiceFlags3);
        wprintf(L"ServiceFlags4:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwServiceFlags4);
        wprintf(L"ProviderFlags:\t\t\t 0x%x\n",
                lpProtocolInfo[i].dwProviderFlags);

        wprintf(L"Protocol Chain length:\t\t %d\n",
                lpProtocolInfo[i].ProtocolChain.ChainLen);

        wprintf(L"\n");
    }

    if (lpProtocolInfo) {
        FREE(lpProtocolInfo);
        lpProtocolInfo = NULL;
    }
    WSACleanup();

    return 0;
}


注意

winsock2.h 标头将 WSAEnumProtocols 定义为一个别名,该别名根据 UNICODE 预处理器常量的定义自动选择此函数的 ANSI 或 Unicode 版本。 将中性编码别名与不中性编码的代码混合使用可能会导致编译或运行时错误不匹配。 有关详细信息,请参阅函数原型的 约定。

要求

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

另请参阅

WSAPROTOCOL_INFO

WSCEnumProtocols

WSCEnumProtocols32

Winsock 函数

Winsock 参考