Share via


CreatePersistentTcpPortReservation, fonction (iphlpapi.h)

La fonction CreatePersistentTcpPortReservation crée une réservation de port TCP persistante pour un bloc consécutif de ports TCP sur l’ordinateur local.

Syntaxe

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

Paramètres

[in] StartPort

Numéro de port TCP de départ dans l’ordre d’octet réseau.

[in] NumberOfPorts

Nombre de numéros de port TCP à réserver.

[out] Token

Pointeur vers un jeton de réservation de port retourné si la fonction réussit.

Valeur retournée

Si la fonction réussit, la valeur de retour est NO_ERROR.

Si la fonction échoue, la valeur de retour est l’un des codes d’erreur suivants.

Code de retour Description
ERROR_ACCESS_DENIED
L’accès est refusé. Cette erreur est retournée dans plusieurs conditions, notamment : l’utilisateur n’a pas les privilèges d’administration requis sur l’ordinateur local ou l’application ne s’exécute pas dans un interpréteur de commandes amélioré en tant qu’administrateur intégré (administrateur RunAs).
ERROR_INVALID_PARAMETER
Un paramètre non valide a été transmis à la fonction.

Cette erreur est retournée si zéro est passé dans les paramètres StartPort ou NumberOfPorts . Cette erreur est également retournée si le paramètre NumberOfPorts est un bloc de ports trop grand selon le paramètre StartPort que le bloc allocable de ports dépasserait le port maximal qui peut être alloué.

ERROR_SHARING_VIOLATION
Le processus ne peut pas accéder au fichier car ce fichier est utilisé par un autre processus. Cette erreur est retournée si un port TCP dans le bloc de ports TCP spécifié par les paramètres StartPort et NumberOfPorts est déjà utilisé. Cette erreur est également retournée si une réservation persistante pour un bloc de ports TCP spécifié par les paramètres StartPort et NumberOfPorts correspond ou chevauche une réservation persistante pour un bloc de ports TCP déjà créé.
Autres
Utilisez FormatMessage pour obtenir la chaîne de message pour l’erreur retournée.

Remarques

La fonction CreatePersistentTcpPortReservation est définie sur Windows Vista et versions ultérieures.

La fonction CreatePersistentTcpPortReservation est utilisée pour ajouter une réservation permanente pour un bloc de ports TCP.

Les applications et services qui doivent réserver des ports se répartissent en deux catégories. La première catégorie inclut les composants qui ont besoin d’un port particulier dans le cadre de leur fonctionnement. Ces composants préfèrent généralement spécifier le port requis au moment de l’installation (dans un manifeste d’application, par exemple). La deuxième catégorie inclut les composants qui ont besoin d’un port ou d’un bloc de ports disponibles au moment de l’exécution.

Ces deux catégories correspondent à des demandes de réservation de port spécifiques et génériques. Les demandes de réservation spécifiques peuvent être persistantes ou en cours d’exécution, tandis que les demandes de réservation de port générique ne sont prises en charge qu’au moment de l’exécution.

La fonction CreatePersistentTcpPortReservation permet à une application ou à un service de réserver un bloc persistant de ports TCP. Les réservations de ports TCP persistants sont enregistrées dans un magasin persistant pour le module TCP dans Windows.

Un appelant obtient une réservation de port persistante en spécifiant le nombre de ports requis et si une plage spécifique est nécessaire. Si la demande peut être satisfaite, la fonction CreatePersistentTcpPortReservation retourne un jeton de ULONG64 opaque unique, qui identifie ensuite la réservation. Une réservation de port TCP persistante peut être libérée en appelant la fonction DeletePersistentTcpPortReservation . Notez que le jeton d’une réservation de port TCP persistante peut changer chaque fois que le système est redémarré.

Windows n’implémente pas la sécurité entre composants pour les réservations persistantes obtenues à l’aide de ces fonctions. Cela signifie que si un composant est autorisé à obtenir des réservations de port persistantes, ce composant obtient automatiquement la possibilité de consommer toutes les réservations de port persistantes accordées à n’importe quel autre composant sur le système. La sécurité au niveau du processus est appliquée pour les réservations d’exécution, mais ce contrôle ne peut pas être étendu aux réservations de port persistantes créées à l’aide de la fonction CreatePersistentTcpPortReservation ou CreatePersistentUdpPortReservation .

Une fois qu’une réservation de port TCP persistante a été obtenue, une application peut demander des affectations de ports à partir de la réservation de port TCP en ouvrant un socket TCP, puis en appelant la fonction WSAIoctl en spécifiant le SIO_ASSOCIATE_PORT_RESERVATION IOCTL et en transmettant le jeton de réservation avant d’émettre un appel à la fonction de liaison sur le socket.

Le SIO_ACQUIRE_PORT_RESERVATION IOCTL peut être utilisé pour demander une réservation d’exécution pour un bloc de ports TCP ou UDP. Pour les réservations de ports d’exécution, le pool de ports exige que les réservations soient consommées à partir du processus sur lequel la réservation a été accordée. Les réservations de port d’exécution durent uniquement tant que la durée de vie du socket sur lequel le SIO_ACQUIRE_PORT_RESERVATION IOCTL a été appelé. En revanche, les réservations de port persistant créées à l’aide de la fonction CreatePersistentTcpPortReservation peuvent être consommées par n’importe quel processus ayant la possibilité d’obtenir des réservations persistantes.

La fonction CreatePersistentTcpPortReservation ne peut être appelée que par un utilisateur connecté en tant que membre du groupe Administrateurs. Si CreatePersistentTcpPortReservation est appelé par un utilisateur qui n’est pas membre du groupe Administrateurs, l’appel de fonction échoue et ERROR_ACCESS_DENIED est retourné. Cette fonction peut également échouer en raison du contrôle de compte d’utilisateur (UAC) sur Windows Vista et versions ultérieures. Si une application qui contient cette fonction est exécutée par un utilisateur connecté en tant que membre du groupe Administrateurs autre que l’administrateur intégré, cet appel échoue, sauf si l’application a été marquée dans le fichier manifeste avec un paramètre requestedExecutionLevel défini sur requireAdministrator. Si l’application ne dispose pas de ce fichier manifeste, un utilisateur connecté en tant que membre du groupe Administrateurs autre que l’administrateur intégré doit alors exécuter l’application dans un interpréteur de commandes amélioré en tant qu’administrateur intégré (administrateur d’exécution) pour que cette fonction réussisse.

Exemples

L’exemple suivant crée une réservation de port TCP persistante, crée un socket et alloue un port à partir de la réservation de port, puis ferme le socket et supprime la réservation de port TCP.

Cet exemple doit être exécuté par un utilisateur membre du groupe Administrateurs. Le moyen le plus simple d’exécuter cet exemple consiste à utiliser un interpréteur de commandes amélioré en tant qu’administrateur intégré (administrateur RunAs).

#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;
}

Configuration requise

Condition requise Valeur
Client minimal pris en charge Windows Vista [applications de bureau uniquement]
Serveur minimal pris en charge Windows Server 2008 [applications de bureau uniquement]
Plateforme cible Windows
En-tête iphlpapi.h
Bibliothèque Iphlpapi.lib
DLL Iphlpapi.dll

Voir aussi

CreatePersistentUdpPortReservation

DeletePersistentTcpPortReservation

DeletePersistentUdpPortReservation

LookupPersistentTcpPortReservation

LookupPersistentUdpPortReservation

SIO_ACQUIRE_PORT_RESERVATION

SIO_ASSOCIATE_PORT_RESERVATION

SIO_RELEASE_PORT_RESERVATION

WSAIoctl

bind