Share via


Funzione CreatePersistentTcpPortReservation (iphlpapi.h)

La funzione CreatePersistentTcpPortReservation crea una prenotazione di porta TCP persistente per un blocco consecutivo di porte TCP nel computer locale.

Sintassi

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

Parametri

[in] StartPort

Numero di porta TCP iniziale nell'ordine di byte di rete.

[in] NumberOfPorts

Numero di numeri di porta TCP da riservare.

[out] Token

Puntatore a un token di prenotazione della porta restituito se la funzione ha esito positivo.

Valore restituito

Se la funzione ha esito positivo, il valore restituito è NO_ERROR.

Se la funzione ha esito negativo, il valore restituito è uno dei codici di errore seguenti.

Codice restituito Descrizione
ERROR_ACCESS_DENIED
Accesso negato. Questo errore viene restituito in diverse condizioni che includono quanto segue: l'utente non dispone dei privilegi amministrativi necessari nel computer locale o l'applicazione non è in esecuzione in una shell avanzata come amministratore predefinito (amministratore RunAs).
ERROR_INVALID_PARAMETER
Un parametro non valido è stato passato alla funzione.

Questo errore viene restituito se zero viene passato nei parametri StartPort o NumberOfPorts . Questo errore viene restituito anche se il parametro NumberOfPorts è troppo grande un blocco di porte a seconda del parametro StartPort che il blocco allocabile di porte supera la porta massima che può essere allocata.

ERROR_SHARING_VIOLATION
Il processo non può accedere al file perché è in uso da un altro processo. Questo errore viene restituito se viene usata una porta TCP nel blocco di porte TCP specificate dai parametri StartPort e NumberOfPorts . Questo errore viene restituito anche se una prenotazione persistente per un blocco di porte TCP specificate dai parametri StartPort e NumberOfPorts corrisponde o sovrappone una prenotazione persistente per un blocco di porte TCP già create.
Altri
Usare FormatMessage per ottenere la stringa di messaggio per l'errore restituito.

Commenti

La funzione CreatePersistentTcpPortReservation viene definita in Windows Vista e versioni successive.

La funzione CreatePersistentTcpPortReservation viene usata per aggiungere una prenotazione persistente per un blocco di porte TCP.

Le applicazioni e i servizi che devono riservare le porte rientrano in due categorie. La prima categoria include componenti che necessitano di una determinata porta nell'ambito dell'operazione. Tali componenti preferiscono in genere specificare la porta richiesta in fase di installazione (ad esempio in un manifesto dell'applicazione). La seconda categoria include componenti che richiedono qualsiasi porta o blocco disponibile di porte in fase di esecuzione.

Queste due categorie corrispondono a richieste di prenotazione delle porte con caratteri jolly e specifiche. Le richieste di prenotazione specifiche possono essere persistenti o in fase di esecuzione, mentre le richieste di prenotazione con porta jolly sono supportate solo in fase di esecuzione.

La funzione CreatePersistentTcpPortReservation consente a un'applicazione o a un servizio di riservare un blocco permanente di porte TCP. Le prenotazioni delle porte TCP persistenti vengono registrate in un archivio permanente per il modulo TCP in Windows.

Un chiamante ottiene una prenotazione di porta persistente specificando il numero di porte necessarie e se è necessario un intervallo specifico. Se la richiesta può essere soddisfatta, la funzione CreatePersistentTcpPortReservation restituisce un token opaco ULONG64 univoco, che identifica successivamente la prenotazione. Una prenotazione della porta TCP persistente può essere rilasciata chiamando la funzione DeletePersistentTcpPortReservation . Si noti che il token per una determinata prenotazione della porta TCP persistente può cambiare ogni volta che il sistema viene riavviato.

Windows non implementa la sicurezza tra componenti per le prenotazioni persistenti ottenute usando queste funzioni. Ciò significa che se un componente ha la possibilità di ottenere prenotazioni di porte persistenti, tale componente ottiene automaticamente la possibilità di utilizzare tutte le prenotazioni di porte persistenti concesse a qualsiasi altro componente nel sistema. La sicurezza a livello di processo viene applicata per le prenotazioni di runtime, ma tale controllo non può essere esteso alle prenotazioni delle porte persistenti create usando la funzione CreatePersistentTcpPortReservation o CreatePersistentUdpPortReservation .

Dopo aver ottenuto una prenotazione della porta TCP persistente, un'applicazione può richiedere assegnazioni di porta dalla prenotazione della porta TCP aprendo un socket TCP, quindi chiamando la funzione WSAIoctl specificando la SIO_ASSOCIATE_PORT_RESERVATION IOCTL e passando il token di prenotazione prima di inviare una chiamata alla funzione di associazione nel socket.

Il SIO_ACQUIRE_PORT_RESERVATION IOCTL può essere usato per richiedere una prenotazione di runtime per un blocco di porte TCP o UDP. Per le prenotazioni delle porte di runtime, il pool di porte richiede che le prenotazioni vengano usate dal processo in cui è stata concessa la prenotazione. Le prenotazioni delle porte di runtime durano solo fino alla durata del socket in cui è stato chiamato il SIO_ACQUIRE_PORT_RESERVATION IOCTL. Al contrario, le prenotazioni delle porte persistenti create usando la funzione CreatePersistentTcpPortReservation possono essere usate da qualsiasi processo con la possibilità di ottenere prenotazioni persistenti.

La funzione CreatePersistentTcpPortReservation può essere chiamata solo da un utente connesso come membro del gruppo Administrators. Se CreatePersistentTcpPortReservation viene chiamato da un utente che non è membro del gruppo Administrators, la chiamata alla funzione avrà esito negativo e ERROR_ACCESS_DENIED viene restituita. Questa funzione può anche non riuscire a causa del controllo account utente (UAC) in Windows Vista e versioni successive. Se un'applicazione contenente questa funzione viene eseguita da un utente connesso come membro del gruppo Administrators diverso dall'amministratore predefinito, questa chiamata avrà esito negativo a meno che l'applicazione non sia stata contrassegnata nel file manifesto con un set requestedExecutionLevel per richiedereAdministrator. Se l'applicazione manca di questo file manifesto, un utente ha eseguito l'accesso come membro del gruppo Administrators diverso dall'amministratore predefinito, deve quindi eseguire l'applicazione in una shell avanzata come amministratore predefinito (amministratore RunAs) per la riuscita di questa funzione.

Esempio

Nell'esempio seguente viene creata una prenotazione di porta TCP persistente, quindi viene creato un socket e viene allocata una porta dalla prenotazione della porta e quindi viene chiuso il socket ed eliminato la prenotazione della porta TCP.

Questo esempio deve essere eseguito da un utente membro del gruppo Administrators. Il modo più semplice per eseguire questo esempio è in una shell avanzata come amministratore predefinito (amministratore 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;
}

Requisiti

Requisito Valore
Client minimo supportato Windows Vista [solo app desktop]
Server minimo supportato Windows Server 2008 [solo app desktop]
Piattaforma di destinazione Windows
Intestazione iphlpapi.h
Libreria Iphlpapi.lib
DLL Iphlpapi.dll

Vedi anche

CreatePersistentUdpPortReservation

DeletePersistentTcpPortReservation

DeletePersistentUdpPortReservation

RicercaPersistentTcpPortReservation

RicercaPersistentUdpPortReservation

SIO_ACQUIRE_PORT_RESERVATION

SIO_ASSOCIATE_PORT_RESERVATION

SIO_RELEASE_PORT_RESERVATION

Wsaioctl

bind