CreatePersistentTcpPortReservation-Funktion (iphlpapi.h)

Die CreatePersistentTcpPortReservation-Funktion erstellt eine permanente TCP-Portreservierung für einen aufeinanderfolgenden Block von TCP-Ports auf dem lokalen Computer.

Syntax

IPHLPAPI_DLL_LINKAGE ULONG CreatePersistentTcpPortReservation(
  [in]  USHORT   StartPort,
  [in]  USHORT   NumberOfPorts,
  [out] PULONG64 Token
);

Parameter

[in] StartPort

Die TCP-Startportnummer in Netzwerkbytereihenfolge.

[in] NumberOfPorts

Die Anzahl der zu reservierenden TCP-Portnummern.

[out] Token

Ein Zeiger auf ein Portreservierungstoken, das zurückgegeben wird, wenn die Funktion erfolgreich ist.

Rückgabewert

Wenn die Funktion erfolgreich ist, wird der Rückgabewert NO_ERROR.

Wenn die Funktion fehlschlägt, ist der Rückgabewert einer der folgenden Fehlercodes.

Rückgabecode Beschreibung
ERROR_ACCESS_DENIED
Zugriff verweigert.“ Dieser Fehler wird unter folgenden Bedingungen zurückgegeben: Dem Benutzer fehlen die erforderlichen Administratorrechte auf dem lokalen Computer, oder die Anwendung wird nicht in einer erweiterten Shell als integrierter Administrator (RunAs-Administrator) ausgeführt.
ERROR_INVALID_PARAMETER
Es wurde ein ungültiger Parameter an die Funktion übergeben.

Dieser Fehler wird zurückgegeben, wenn null im StartPort- oder NumberOfPorts-Parameter übergeben wird. Dieser Fehler wird auch zurückgegeben, wenn der Parameter NumberOfPorts je nach StartPort-Parameter zu groß ist, dass der zuweisungsfähige Portblock den maximalen Port überschreiten würde, der zugewiesen werden kann.

ERROR_SHARING_VIOLATION
Der Prozess kann nicht auf die Datei zugreifen, da sie bereits von einem anderen Prozess verwendet wird. Dieser Fehler wird zurückgegeben, wenn bereits ein TCP-Port im Block der TCP-Ports verwendet wird, die durch die Parameter StartPort und NumberOfPorts angegeben sind. Dieser Fehler wird auch zurückgegeben, wenn eine persistente Reservierung für einen Block von TCP-Ports, die durch die Parameter StartPort und NumberOfPorts angegeben wird, einer persistenten Reservierung für einen bereits erstellten Block von TCP-Ports entspricht oder sich überschneidet.
Andere
Verwenden Sie FormatMessage , um die Nachrichtenzeichenfolge für den zurückgegebenen Fehler abzurufen.

Hinweise

Die CreatePersistentTcpPortReservation-Funktion ist unter Windows Vista und höher definiert.

Die CreatePersistentTcpPortReservation-Funktion wird verwendet, um eine persistente Reservierung für einen Block von TCP-Ports hinzuzufügen.

Anwendungen und Dienste, die Ports reservieren müssen, fallen in zwei Kategorien. Die erste Kategorie umfasst Komponenten, die einen bestimmten Port als Teil ihres Betriebs benötigen. Solche Komponenten bevorzugen in der Regel, ihren erforderlichen Port zur Installationszeit anzugeben (z. B. in einem Anwendungsmanifest). Die zweite Kategorie enthält Komponenten, die zur Laufzeit einen verfügbaren Port oder Block von Ports benötigen.

Diese beiden Kategorien entsprechen spezifischen Und Denkplatzhalter-Portreservierungsanforderungen. Bestimmte Reservierungsanforderungen können persistent oder Runtime sein, während Die Reservierungsanforderungen für Die Reservierung von Freihalterports nur zur Laufzeit unterstützt werden.

Die CreatePersistentTcpPortReservation-Funktion bietet einer Anwendung oder einem Dienst die Möglichkeit, einen persistenten Block von TCP-Ports zu reservieren. Reservierungen für persistente TCP-Ports werden in einem persistenten Speicher für das TCP-Modul in Windows aufgezeichnet.

Ein Aufrufer ruft eine dauerhafte Portreservierung ab, indem er angibt, wie viele Ports erforderlich sind und ob ein bestimmter Bereich benötigt wird. Wenn die Anforderung erfüllt werden kann, gibt die CreatePersistentTcpPortReservation-Funktion ein eindeutiges undurchsichtiges ULONG64 Token zurück, das anschließend die Reservierung identifiziert. Eine persistente TCP-Portreservierung kann durch Aufrufen der Funktion DeletePersistentTcpPortReservation freigegeben werden. Beachten Sie, dass sich das Token für eine bestimmte permanente TCP-Portreservierung bei jedem Neustart des Systems ändern kann.

Windows implementiert keine komponentenübergreifende Sicherheit für persistente Reservierungen, die mithilfe dieser Funktionen abgerufen werden. Dies bedeutet, dass, wenn einer Komponente die Möglichkeit gewährt wird, persistente Portreservierungen abzurufen, diese Komponente automatisch die Möglichkeit erhält, alle persistenten Portreservierungen zu nutzen, die einer anderen Komponente im System gewährt werden. Die Sicherheit auf Prozessebene wird für Laufzeitreservierungen erzwungen, aber ein solches Steuerelement kann nicht auf persistente Portreservierungen erweitert werden, die mit der Funktion CreatePersistentTcpPortReservation oder CreatePersistentUdpPortReservation erstellt wurden.

Sobald eine permanente TCP-Portreservierung abgerufen wurde, kann eine Anwendung Portzuweisungen von der TCP-Portreservierung anfordern, indem sie einen TCP-Socket öffnet und dann die WSAIoctl-Funktion aufruft, die den SIO_ASSOCIATE_PORT_RESERVATION IOCTL angibt und das Reservierungstoken übergibt, bevor sie einen Aufruf der Bindungsfunktion im Socket ausgibt.

Die SIO_ACQUIRE_PORT_RESERVATION IOCTL kann verwendet werden, um eine Laufzeitreservierung für einen Block von TCP- oder UDP-Ports anzufordern. Für Laufzeitportreservierungen erfordert der Portpool, dass Reservierungen aus dem Prozess genutzt werden, für den die Reservierung gewährt wurde. Laufzeitportreservierungen dauern nur so lange wie die Lebensdauer des Sockets, für den die SIO_ACQUIRE_PORT_RESERVATION IOCTL aufgerufen wurde. Im Gegensatz dazu können persistente Portreservierungen, die mit der Funktion CreatePersistentTcpPortReservation erstellt wurden, von jedem Prozess genutzt werden, der persistente Reservierungen abrufen kann.

Die CreatePersistentTcpPortReservation-Funktion kann nur von einem Benutzer aufgerufen werden, der als Mitglied der Gruppe Administratoren angemeldet ist. Wenn CreatePersistentTcpPortReservation von einem Benutzer aufgerufen wird, der kein Mitglied der Gruppe Administratoren ist, schlägt der Funktionsaufruf fehl, und ERROR_ACCESS_DENIED wird zurückgegeben. Diese Funktion kann auch aufgrund der Benutzerkontensteuerung (User Account Control, UAC) unter Windows Vista und höher fehlschlagen. Wenn eine Anwendung, die diese Funktion enthält, von einem Benutzer ausgeführt wird, der nicht als mitglied der Gruppe Administratoren als der integrierte Administrator angemeldet ist, schlägt dieser Aufruf fehl, es sei denn, die Anwendung wurde in der Manifestdatei mit einem requestedExecutionLevel-Wert gekennzeichnet, der auf requireAdministrator festgelegt ist. Wenn der Anwendung diese Manifestdatei fehlt, muss ein Benutzer, der sich als anderes Mitglied der Administratorgruppe als der integrierte Administrator angemeldet hat, die Anwendung dann in einer erweiterten Shell als integrierter Administrator (RunAs-Administrator) ausführen, damit diese Funktion erfolgreich ist.

Beispiele

Im folgenden Beispiel wird eine permanente TCP-Portreservierung erstellt, dann ein Socket erstellt und ein Port aus der Portreservierung zugeordnet, dann wird der Socket geschlossen und die TCP-Portreservierung gelöscht.

Dieses Beispiel muss von einem Benutzer ausgeführt werden, der Mitglied der Gruppe Administratoren ist. Die einfachste Möglichkeit zum Ausführen dieses Beispiels besteht in einer erweiterten Shell als integrierter Administrator (RunAs-Administrator).

#ifndef UNICODE
#define UNICODE
#endif

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <Windows.h.>
#include <winsock2.h>
#include <mstcpip.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>

// Need to link with iphlpapi.lib
#pragma comment(lib, "iphlpapi.lib")

// Need to link with Ws2_32.lib for Winsock functions
#pragma comment(lib, "ws2_32.lib")

int wmain(int argc, WCHAR ** argv)
{

    // Declare and initialize variables

    int startPort = 0;         // host byte order
    int numPorts = 0;
    USHORT startPortns = 0;    // Network byte order
    ULONG64 resToken = { 0 };

    unsigned long status = 0;

    WSADATA wsaData = { 0 };
    int iResult = 0;

    SOCKET sock = INVALID_SOCKET;
    int iFamily = AF_INET;
    int iType = SOCK_STREAM;
    int iProtocol = IPPROTO_TCP;

    DWORD bytesReturned = 0;


    // Note that the sockaddr_in struct works only with AF_INET not AF_INET6
    // An application needs to use the sockaddr_in6 for AF_INET6
    sockaddr_in service; 
    sockaddr_in sockName;
    int nameLen = sizeof(sockName);
    
    // Validate the parameters
    if (argc != 3) {
        wprintf(L"usage: %s <Starting Port> <Number of Ports>\n",
             argv[0]);
        wprintf(L"Creates a persistent TCP port reservation\n");
        wprintf(L"Example usage:\n");
        wprintf(L"   %s 5000 20\n", argv[0]);
        wprintf(L"   where StartPort=5000 NumPorts=20");
        return 1;
    }

    startPort = _wtoi(argv[1]);
    if (startPort < 0 || startPort > 65535) {
        wprintf(L"Starting point must be either 0 or between 1 and 65,535\n");
        return 1;
    }
    startPortns = htons((USHORT) startPort);

    numPorts = _wtoi(argv[2]);
    if (numPorts < 0) {
        wprintf(L"Number of ports must be a positive number\n");
        return 1;
    }

    status =
        CreatePersistentTcpPortReservation((USHORT) startPortns, (USHORT) numPorts,
                                           &resToken);
    if (status != NO_ERROR) {
        wprintf(L"CreatePersistentTcpPortReservation returned error: %ld\n", status);
        return 1;
    }

    wprintf(L"CreatePersistentTcpPortReservation call succeeded\n");
    wprintf(L"  Token = %I64d\n", resToken);

    // Comment out this block if you don't want to create a socket and associate it with the 
    // persistent reservation

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

    sock = socket(iFamily, iType, iProtocol);
    if (sock == INVALID_SOCKET)
        wprintf(L"socket function failed with error = %d\n", WSAGetLastError());
    else {
        wprintf(L"socket function succeeded\n");

        iResult =
            WSAIoctl(sock, SIO_ASSOCIATE_PORT_RESERVATION, (LPVOID) & resToken,
                     sizeof (ULONG64), NULL, 0, &bytesReturned, NULL, NULL);
        if (iResult != 0) {
            wprintf
                (L"WSAIoctl(SIO_ASSOCIATE_PORT_RESERVATION) failed with error = %d\n",
                 WSAGetLastError());
        } else {
            wprintf(L"WSAIoctl(SIO_ASSOCIATE_PORT_RESERVATION) succeeded, bytesReturned = %u\n", 
                bytesReturned);                

            service.sin_family = AF_INET;
            service.sin_addr.s_addr = INADDR_ANY;
            service.sin_port = 0;

            iResult = bind(sock, (SOCKADDR*) &service, sizeof(service) );
            if (iResult == SOCKET_ERROR)
                wprintf(L"bind failed with error = %d\n", WSAGetLastError());
            else {
                wprintf(L"bind succeeded\n");
                iResult = getsockname(sock, (SOCKADDR*) &sockName, &nameLen);
                if (iResult == SOCKET_ERROR) 
                    wprintf(L"getsockname failed with error = %d\n", WSAGetLastError() );
                else {
                    wprintf(L"getsockname succeeded\n");
                    wprintf(L"Port number allocated = %u\n", ntohs(sockName.sin_port) );
                }
            }                  
        }

        if (sock != INVALID_SOCKET) {
            iResult = closesocket(sock);
            if (iResult == SOCKET_ERROR) {
                wprintf(L"closesocket failed with error = %d\n", WSAGetLastError());
                WSACleanup();
            }
        }
    }

    // comment out this block of code if you don't want to delete the reservation just created
    status = DeletePersistentTcpPortReservation((USHORT) startPortns, (USHORT) numPorts);
    if (status != NO_ERROR) {
        wprintf(L"DeletePersistentTcpPortReservation returned error: %ld\n", status);
        return 1;
    }
    wprintf(L"DeletePersistentTcpPortReservation call succeeded\n");

    return 0;
}

Anforderungen

Anforderung Wert
Unterstützte Mindestversion (Client) Windows Vista [nur Desktop-Apps]
Unterstützte Mindestversion (Server) Windows Server 2008 [nur Desktop-Apps]
Zielplattform Windows
Kopfzeile iphlpapi.h
Bibliothek Iphlpapi.lib
DLL Iphlpapi.dll

Weitere Informationen

CreatePersistentUdpPortReservation

DeletePersistentTcpPortReservation

DeletePersistentUdpPortReservation

LookupPersistentTcpPortReservation

LookupPersistentUdpPortReservation

SIO_ACQUIRE_PORT_RESERVATION

SIO_ASSOCIATE_PORT_RESERVATION

SIO_RELEASE_PORT_RESERVATION

WSAIoctl

bind