Condividi tramite


codice di controllo SIO_RELEASE_PORT_RESERVATION

Descrizione

Il codice di controllo SIO_RELEASE_PORT_RESERVATION rilascia una prenotazione di runtime per un blocco di porte TCP o UDP. La prenotazione di runtime da rilasciare deve essere stata ottenuta dal processo di emissione usando il SIO_ACQUIRE_PORT_RESERVATION IOCTL.

Per eseguire questa operazione, chiamare la funzione WSAIoctl o WSPIoctl con i parametri seguenti.

int WSAIoctl(
  (socket) s,             // descriptor identifying a socket
  SIO_RELEASE_PORT_RESERVATION, // dwIoControlCode
  (LPVOID) lpvInBuffer,  // pointer to a INET_PORT_RESERVATION_TOKEN structure
  (DWORD) cbInBuffer,    // size, in bytes, of the input buffer
  NULL,           // lpvOutBuffer is a pointer to the output buffer
  0,              // cbOutBuffer is the size, in bytes, of the output buffer
  (LPDWORD) lpcbBytesReturned,    // number of bytes returned
  (LPWSAOVERLAPPED) lpOverlapped,   // OVERLAPPED structure
  (LPWSAOVERLAPPED_COMPLETION_ROUTINE) lpCompletionRoutine,  // completion routine
);

int WSPIoctl(
  (socket) s,             // descriptor identifying a socket
  SIO_RELEASE_PORT_RESERVATION, // dwIoControlCode
  (LPVOID) lpvInBuffer,  // pointer to a INET_PORT_RESERVATION_TOKEN structure
  (DWORD) cbInBuffer,    // size, in bytes, of the input buffer
  NULL,           // lpvOutBuffer is a pointer to the output buffer
  0,              // cbOutBuffer is the size, in bytes, of the output buffer
  (LPDWORD) lpcbBytesReturned,    // number of bytes returned
  (LPWSAOVERLAPPED) lpOverlapped,   // OVERLAPPED structure
  (LPWSAOVERLAPPED_COMPLETION_ROUTINE) lpCompletionRoutine,  // completion routine
  (LPWSATHREADID) lpThreadId,   // a WSATHREADID structure
  (LPINT) lpErrno   // a pointer to the error code.
);

Parametri

s

Descrittore che identifica un socket.

dwIoControlCode

Codice di controllo per l'operazione. Usare SIO_RELEASE_PORT_RESERVATION per questa operazione.

lpvInBuffer

Puntatore al buffer di input. Questo parametro contiene un puntatore a una struttura INET_PORT_RESERVATION_TOKEN con il token per la prenotazione della porta TCP o UDP da rilasciare.

cbInBuffer

Dimensioni, in byte, del buffer di input. Questo parametro deve essere almeno la dimensione della struttura INET_PORT_RESERVATION_TOKEN .

lpvOutBuffer

Puntatore al buffer di output. Questo parametro non viene usato per questa operazione.

cbOutBuffer

Dimensioni, in byte, del buffer di output. Questo parametro deve essere impostato su zero.

lpcbBytesReturned

Puntatore a una variabile che riceve le dimensioni, in byte, dei dati archiviati nel buffer di output.

Se il buffer di output è troppo piccolo, la chiamata ha esito negativo, WSAGetLastError restituisce WSAEINVAL e il parametro lpcbBytesReturned punta a un valore DWORD pari a zero.

Se lpOverlapped è NULL, il valore DWORD puntato al parametro lpcbBytesReturned restituito in una chiamata riuscita non può essere zero.

Se il parametro lpOverlapped non è NULL per i socket sovrapposti, le operazioni che non possono essere completate immediatamente verranno avviate e il completamento verrà indicato in un secondo momento. Il valore DWORD indicato dal parametro lpcbBytesReturned restituito può essere zero poiché le dimensioni dei dati archiviati non possono essere determinate fino al completamento dell'operazione sovrapposta. Lo stato di completamento finale può essere recuperato quando il metodo di completamento appropriato viene segnalato al termine dell'operazione.

lpvOverlapped

Puntatore a una struttura WSAOVERLAPPED .

Se il socket s è stato creato senza l'attributo sovrapposto, il parametro lpOverlapped viene ignorato .

Se s è stato aperto con l'attributo sovrapposto e il parametro lpOverlapped non è NULL, l'operazione viene eseguita come operazione sovrapposta (asincrona). In questo caso, il parametro lpOverlapped deve puntare a una struttura WSAOVERLAPPED valida.

Per le operazioni sovrapposte, la funzione WSAIoctl o WSPIoctl restituisce immediatamente e il metodo di completamento appropriato viene segnalato al termine dell'operazione. In caso contrario, la funzione non restituisce finché l'operazione non è stata completata o si verifica un errore.

lpCompletionRoutine

Tipo: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE

Puntatore alla routine di completamento chiamata quando l'operazione è stata completata (ignorata per socket non sovrapposti).

lpThreadId

Puntatore a una struttura WSATHREADID da usare dal provider in una chiamata successiva a WPUQueueApc. Il provider deve archiviare la struttura WSATHREADID a cui fa riferimento (non lo stesso puntatore) fino a quando la funzione WPUQueueApc restituisce.

Nota Questo parametro si applica solo alla funzione WSPIoctl .

lpErrno

Puntatore al codice di errore.

Nota Questo parametro si applica solo alla funzione WSPIoctl .

Valore restituito

Se l'operazione viene completata correttamente, la funzione WSAIoctl o WSPIoctl restituisce zero.

Se l'operazione ha esito negativo o è in sospeso, la funzione WSAIoctl o WSPIoctl restituisce SOCKET_ERROR. Per ottenere informazioni sull'errore estese, chiamare WSAGetLastError.

Codice di errore Significato
WSA_IO_PENDING L'operazione di I/O sovrapposta è in corso. Questo valore viene restituito se un'operazione sovrapposta è stata avviata correttamente e il completamento verrà indicato in un secondo momento.
WSA_OPERATION_ABORTED Operazione di I/O annullata per uscita da un thread o su richiesta di un'applicazione. Questo errore viene restituito se un'operazione sovrapposta è stata annullata a causa della chiusura del socket o dell'esecuzione del comando IOCTL SIO_FLUSH.
WSAEFAULT Il sistema ha rilevato un indirizzo puntatore non valido nel tentativo di usare un argomento puntatore in una chiamata. Questo errore viene restituito del parametro lpOverlapped o lpCompletionRoutine non è totalmente contenuto in una parte valida dello spazio degli indirizzi utente.
WSAEINPROGRESS È in corso un'operazione di blocco. Questo errore viene restituito se la funzione viene richiamata quando è in corso un callback.
WSAEINTR Un'operazione di blocco è stata interrotta da una chiamata a WSACancelBlockingCall. Questo errore viene restituito se un'operazione di blocco è stata interrotta.
WSAEINVAL Argomento fornito non valido. Questo errore viene restituito se il parametro dwIoControlCode non è un comando valido o un parametro di input specificato non è accettabile oppure il comando non è applicabile al tipo di socket specificato.
WSAENETDOWN Rete inattiva rilevata durante l'operazione del socket. Questo errore viene restituito se il sottosistema di rete non è riuscito.
WSAENOTSOCK Un'operazione è stata tentata su un elemento che non è un socket. Questo errore viene restituito se il descrittore s non è un socket.
WSAEOPNOTSUPP L'operazione tentata non è supportata per il tipo di oggetto a cui viene fatto riferimento. Questo errore viene restituito se il comando IOCTL specificato non è supportato. Questo errore viene restituito anche se il SIO_RELEASE_PORT_RESERVATION IOCTL non è supportato dal provider di trasporto. Questo errore viene restituito anche quando viene eseguito un tentativo di utilizzo del SIO_RELEASE_PORT_RESERVATION IOCTL in un socket diverso da UDP o TCP.

Commenti

Il SIO_RELEASE_PORT_RESERVATION IOCTL è supportato in Windows Vista e versioni successive del sistema operativo.

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.

Il SIO_ACQUIRE_PORT_RESERVATION IOCTL viene 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 di porte persistenti create usando la funzione CreatePersistentTcpPortReservation o CreatePersistentUdpPortReservation possono essere usate da qualsiasi processo con la possibilità di ottenere prenotazioni persistenti.

Il SIO_RELEASE_PORT_RESERVATION IOCTL viene usato per rilasciare una prenotazione di runtime per un blocco di porte TCP o UDP.

Se entrambi i parametri lpOverlapped e lpCompletionRoutine sono NULL, il socket in questa funzione verrà considerato come socket non sovrapposto. Per un socket non sovrapposto, i parametri lpOverlapped e lpCompletionRoutine vengono ignorati, ad eccezione del fatto che la funzione può bloccare se socket s è in modalità di blocco. Se socket s è in modalità non bloccabile, questa funzione continuerà a bloccarsi poiché questa particolare modalità IOCTL non supporta la modalità di blocco.

Per i socket sovrapposti, le operazioni che non possono essere completate immediatamente verranno avviate e il completamento verrà indicato in un secondo momento.

Qualsiasi IOCTL può bloccare a tempo indefinito, a seconda dell'implementazione del provider di servizi. Se l'applicazione non può tollerare il blocco in una chiamata di funzione WSAIoctl o WSPIoctl , è consigliabile che le operazioni di I/O sovrapposte siano consigliate per IOCTL che sono particolarmente probabili bloccare.

Il SIO_RELEASE_PORT_RESERVATION IOCTL può avere esito negativo con WSAEINTR o WSA_OPERATION_ABORTED nei casi seguenti:

  • La richiesta viene annullata da I/O Manager.
  • Il socket è chiuso.

Esempio

L'esempio seguente acquisisce una prenotazione della porta di runtime e quindi rilascia la prenotazione della porta di runtime.

#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 <stdio.h>
#include <stdlib.h>

// 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

    INET_PORT_RANGE portRange = { 0 };
    INET_PORT_RESERVATION_INSTANCE portRes = { 0 };

    unsigned long status = 0;

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

    SOCKET sock = INVALID_SOCKET;
    int iFamily = AF_INET;
    int iType = 0;
    int iProtocol = 0;

    SOCKET sockRes = INVALID_SOCKET;

    DWORD bytesReturned = 0;

    // Validate the parameters
    if (argc != 6) {
        wprintf
            (L"usage: %s <addressfamily> <type> <protocol> <StartingPort> <NumberOfPorts>\n",
             argv[0]);
        wprintf(L"Opens a socket for the specified family, type, & protocol\n");
        wprintf
            (L"and then acquires a runtime port reservation for the protocol specified\n");
        wprintf(L"%ws example usage\n", argv[0]);
        wprintf(L"   %ws 2 2 17 5000 20\n", argv[0]);
        wprintf(L"   where AF_INET=2 SOCK_DGRAM=2 IPPROTO_UDP=17 StartPort=5000 NumPorts=20", argv[0]);

        return 1;
    }

    iFamily = _wtoi(argv[1]);
    iType = _wtoi(argv[2]);
    iProtocol = _wtoi(argv[3]);

    startPort = _wtoi(argv[4]);
    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[5]);
    if (numPorts < 0) {
        wprintf(L"Number of ports must be a positive number\n");
        return 1;
    }

    portRange.StartPort = startPortns;
    portRange.NumberOfPorts = (USHORT) numPorts;

    // 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());
        WSACleanup();
        return 1;
    } else {
        wprintf(L"socket function succeeded\n");

        iResult =
            WSAIoctl(sock, SIO_ACQUIRE_PORT_RESERVATION, (LPVOID) & portRange,
                     sizeof (INET_PORT_RANGE), (LPVOID) & portRes,
                     sizeof (INET_PORT_RESERVATION_INSTANCE), &bytesReturned, NULL, NULL);
        if (iResult != 0) {
            wprintf(L"WSAIoctl(SIO_ACQUIRE_PORT_RESERVATION) failed with error = %d\n",
                    WSAGetLastError());
            closesocket(sock);
            WSACleanup();
            return 1;
        } else {
            wprintf
                (L"WSAIoctl(SIO_ACQUIRE_PORT_RESERVATION) succeeded, bytesReturned = %u\n",
                 bytesReturned);
            wprintf(L"  Starting port=%d,  Number of Ports=%d, Token=%I64d\n",
                    htons(portRes.Reservation.StartPort),
                    portRes.Reservation.NumberOfPorts, portRes.Token);

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

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

    WSACleanup();

    return 0;
}

Vedi anche

CreatePersistentTcpPortReservation

CreatePersistentUdpPortReservation

DeletePersistentTcpPortReservation

DeletePersistentUdpPortReservation

INET_PORT_RESERVATION_TOKEN

LookupPersistentTcpPortReservation

LookupPersistentUdpPortReservation

SIO_ACQUIRE_PORT_RESERVATION

SIO_ASSOCIATE_PORT_RESERVATION

Socket

WSAGetLastError

WSAGetOverlappedResult

Wsaioctl

WSAOVERLAPPED

WSASocketA

WSASocketW