共用方式為


WSAEnumProtocolsA 函式 (winsock2.h)

WSAEnumProtocols 函式會擷取可用傳輸通訊協議的相關信息。

語法

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

參數

[in] lpiProtocols

NULLiProtocol 值的終止陣列。 此參數是選擇性的;如果 lpiProtocols 為 NULL,則會傳回所有可用通訊協議的相關信息。 否則,只會針對陣列中所列的通訊協定擷取資訊。

[out] lpProtocolBuffer

填入 WSAPROTOCOL_INFO 結構的緩衝區指標。

[in, out] lpdwBufferLength

在輸入時,lpProtocolBuffer 緩衝區中傳遞至 WSAEnumProtocols的位元元組數目。 在輸出中,可傳遞至 WSAEnumProtocols 的緩衝區大小下限,以擷取所有要求的資訊。 此例程無法列舉多個呼叫;傳入的緩衝區必須夠大,才能保存所有專案,讓例程成功。 這可減少 API 的複雜性,而且不應該造成問題,因為計算機上載入的通訊協定數目通常很小。

傳回值

如果沒有發生錯誤,WSAEnumProtocols 會傳回要報告的通訊協定數目。 否則,會傳回SOCKET_ERROR值,而且可以呼叫 WSAGetLastError來擷取特定的錯誤碼。

錯誤碼 意義
WSANOTINITIALISED
在使用此函式之前,必須先進行成功的 WSAStartup 呼叫。
WSAENETDOWN
網路子系統失敗。
WSAEINPROGRESS
封鎖的 Windows Sockets 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 函式會排除服務提供者在 dwProviderFlags 中以 PFL_HIDDEN 旗標設定的通訊協定,WSAPROTOCOL_INFO 結構 成員,以向 Ws2_32.dll 指出此通訊協定不應在 WSAEnumProtocols 函式所產生的結果緩衝區中傳回。 此外,WSAEnumProtocols 函式不會傳回鏈結長度為一或更高(LSP 提供者)之 WSAPROTOCOL_INFO 結構的數據。 WSAEnumProtocols 只會傳回缺少 PFL_HIDDEN 旗標且沒有零通訊協定鏈結長度的基底通訊協定和通訊協定鏈結資訊。

lpProtocolBuffer 所指向的緩衝區中會提供 WSAPROTOCOL_INFO 結構, 每個要求的通訊協定。 如果指定的緩衝區不夠大(如 lpdwBufferLength 的輸入值所指示),則會更新 lpdwBufferLeng th 所指向的值,以指出所需的緩衝區大小。 然後,應用程式應該會取得足夠大的緩衝區,並再次呼叫 WSAEnumProtocols

緩衝區中出現 WSAPROTOCOL_INFO 結構的順序與服務提供者使用 WS2_32.DLL 註冊通訊協定項目的順序,或是透過 Windows Sockets 應用程式或為建立預設 TCP/IP 提供者而提供的任何後續重新排序順序一致。

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 標頭會根據 UNICODE 預處理器常數的定義,將 WSAEnumProtocols 定義為自動選取此函式的 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 參考