Code de contrôle SIO_ACQUIRE_PORT_RESERVATION

Description

Le code de contrôle de _ _ _ réservation de port SIO acquiert une réservation d’exécution pour un bloc de ports TCP ou UDP.

Pour effectuer cette opération, appelez la fonction WSAIoctl ou WSPIoctl avec les paramètres suivants.

int WSAIoctl(
  (socket) s,             // descriptor identifying a socket
  SIO_ACQUIRE_PORT_RESERVATION, // dwIoControlCode
  (LPVOID) lpvInBuffer,  // pointer to an INET_PORT_RANGE structure
  (DWORD) cbInBuffer,    // size, in bytes, of the input buffer
  (LPVOID) lpvOutBuffer,             // pointer to an INET_PORT_RESERVATION_INSTANCE structure
  (DWORD) cbOutBuffer,   // 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_ACQUIRE_PORT_RESERVATION, // dwIoControlCode
  (LPVOID) lpvInBuffer,  // pointer to an INET_PORT_RANGE structure
  (DWORD) cbInBuffer,    // size, in bytes, of the input buffer
  (LPVOID) lpvOutBuffer,             // pointer to a INET_PORT_RESERVATION_INSTANCE structure
  (DWORD) cbOutBuffer,   // 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.
);

Paramètres

s

Descripteur identifiant un Socket.

dwIoControlCode

Code de contrôle de l’opération. Utilisez SIO _ Acquire _ port _ reservation pour cette opération.

lpvInBuffer

Pointeur vers la mémoire tampon d’entrée. Ce paramètre contient un pointeur vers une structure de _ _ plage de ports inet qui spécifie le numéro du point de départ et le nombre de ports à réserver.

cbInBuffer

Taille, en octets, de la mémoire tampon d’entrée. Ce paramètre doit correspondre à la taille de la structure de l' _ _ étendue du port inet .

lpvOutBuffer

Pointeur vers la mémoire tampon de sortie. En cas de sortie réussie, ce paramètre contient un pointeur vers une structure d' _ instance de _ réservation _ de port inet .

cbOutBuffer

Taille, en octets, de la mémoire tampon de sortie. Ce paramètre doit avoir au moins la taille de la structure de l' _ instance de _ réservation _ du port inet .

lpcbBytesReturned

Pointeur vers une variable qui reçoit la taille, en octets, des données stockées dans la mémoire tampon de sortie.

Si la mémoire tampon de sortie est trop petite, l’appel échoue, WSAGetLastError retourne WSAEINVALet le paramètre LpcbBytesReturned pointe vers une valeur DWORD égale à zéro.

Si lpOverlapped a la valeur null, la valeur DWORD vers laquelle pointe le paramètre lpcbBytesReturned retourné sur un appel réussi ne peut pas être égale à zéro.

Si le paramètre lpOverlapped n’a pas la valeur null pour les sockets superposés, les opérations qui ne peuvent pas être terminées immédiatement seront lancées et l’achèvement sera indiqué ultérieurement. La valeur DWORD pointée par le paramètre lpcbBytesReturned retourné peut être égale à zéro, car la taille des données stockées ne peut pas être déterminée tant que l’opération avec chevauchement n’est pas terminée. L’état d’achèvement final peut être récupéré lorsque la méthode d’achèvement appropriée est signalée lorsque l’opération est terminée.

lpvOverlapped

Pointeur vers une structure WSAOVERLAPPED .

Si le socket s a été créé sans l’attribut Overlapped, le paramètre lpOverlapped est ignoré.

Si s a été ouvert avec l’attribut Overlapped et que le paramètre lpOverlapped n’a pas la valeur null, l’opération est exécutée en tant qu’opération Overlapped (asynchrone). Dans ce cas, le paramètre lpOverlapped doit pointer vers une structure WSAOVERLAPPED valide.

Pour les opérations avec chevauchement, la fonction WSAIoctl ou WSPIoctl retourne immédiatement, et la méthode d’achèvement appropriée est signalée lorsque l’opération est terminée. Sinon, la fonction ne retourne pas jusqu’à ce que l’opération soit terminée ou qu’une erreur se produise.

lpCompletionRoutine

Type : _ In_opt _ LPWSAOVERLAPPED_COMPLETION_ROUTINE

Pointeur vers la routine de saisie semi-automatique appelée lorsque l’opération est terminée (ignoré pour les sockets non superposés).

lpThreadId

Pointeur vers une structure WSATHREADID qui doit être utilisée par le fournisseur dans un appel ultérieur à WPUQueueApc. Le fournisseur doit stocker la structure WSATHREADID référencée (pas le pointeur vers le même) jusqu’à ce que la fonction WPUQueueApc soit retournée.

Remarque Ce paramètre s’applique uniquement à la fonction WSPIoctl .

lpErrno

Pointeur vers le code d’erreur.

Remarque Ce paramètre s’applique uniquement à la fonction WSPIoctl .

Valeur retournée

Si l’opération se termine correctement, la fonction WSAIoctl ou WSPIoctl retourne la valeur zéro.

Si l’opération échoue ou est en attente, la fonction WSAIoctl ou WSPIoctl retourne une _ erreur de socket. Pour afficher les informations d’erreur étendues, appelez WSAGetLastError.

Code d'erreur Signification
_e/s WSA _ en attente L’opération d’e/s avec chevauchement est en cours. Cette valeur est retournée si une opération avec chevauchement a été correctement initiée et que son achèvement sera indiqué ultérieurement.
_opération WSA _ abandonnée L’opération d’e/s a été annulée en raison de la sortie d’un thread ou d’une demande de l’application. Cette erreur est retournée si une opération avec chevauchement a été annulée en raison de la fermeture du socket ou de l’exécution de la commande SIO _ flush ioctl.
WSAEFAULT Le système a détecté une adresse de pointeur non valide lors de la tentative d’utilisation d’un argument de pointeur dans un appel. Cette erreur est retournée par le paramètre lpvInBuffer, lpvoutBuffer, lpcbBytesReturned, lpOverlapped ou lpCompletionRoutine n’est pas entièrement contenu dans une partie valide de l’espace d’adressage de l’utilisateur.
WSAEINPROGRESS Une opération de blocage est actuellement en cours d'exécution. Cette erreur est retournée si la fonction est appelée lorsqu’un rappel est en cours.
WSAEINTR Une opération de blocage a été interrompue par un appel à WSACancelBlockingCall. Cette erreur est retournée si une opération de blocage a été interrompue.
WSAEINVAL Argument non valide fourni. Cette erreur est retournée si le paramètre dwIoControlCode n’est pas une commande valide, si un paramètre d’entrée spécifié n’est pas acceptable ou si la commande n’est pas applicable au type de socket spécifié.
WSAENETDOWN Une opération de socket a rencontré un réseau inactif. Cette erreur est retournée si le sous-système réseau a échoué.
WSAENOTSOCK Une opération a été tentée sur un qui n’est pas un Socket. Cette erreur est retournée si le descripteur n’est pas un Socket.
WSAEOPNOTSUPP L’opération tentée n’est pas prise en charge pour le type d’objet référencé. Cette erreur est retournée si la commande IOCTL spécifiée n’est pas prise en charge. Cette erreur est également retournée si l’IOCTL SIO _ Acquire _ port _ reservation n’est pas prise en charge par le fournisseur de transport. Cette erreur est également retournée quand une tentative d’utilisation de l’IOCTL de _ réservation de _ port _ SIO Acquire est effectuée sur un socket autre que UDP ou TCP.

Notes

L’IOCTL SIO _ Acquire _ port _ reservation est prise en charge sur Windows Vista et les versions ultérieures du système d’exploitation.

Les applications et les services qui doivent réserver des ports sont répartis en deux catégories. La première catégorie comprend des composants qui ont besoin d’un port particulier dans le cadre de leur fonctionnement. De tels 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 comprend des 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 génériques et spécifiques. Les demandes de réservation spécifiques peuvent être persistantes ou d’exécution, tandis que les demandes de réservation de port génériques sont uniquement prises en charge au moment de l’exécution.

L’IOCTL SIO _ Acquire _ port _ reservation est utilisée pour demander une réservation d’exécution pour un bloc de ports TCP ou UDP. Pour les réservations de port d’exécution, le pool de ports requiert 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 l’IOCTL SIO _ Acquire _ port _ reservation a été appelée. En revanche, les réservations de port persistantes créées à l’aide de la fonction CreatePersistentTcpPortReservation ou CreatePersistentUdpPortReservation peuvent être consommées par n’importe quel processus ayant la possibilité d’obtenir des réservations persistantes.

Une fois qu’une réservation de port TCP ou UDP du runtime a été obtenue, une application peut demander des affectations de port à partir de la réservation de port en ouvrant un socket TCP ou UDP, puis en appelant la fonction WSAIoctl en spécifiant l’IOCTL de réservation de _ _ port _ SIO Associate et en passant le jeton de réservation avant d’émettre un appel à la fonction de liaison sur le Socket.

Si les deux paramètres lpOverlapped et lpCompletionRoutine sont null, le socket dans cette fonction sera traité comme un socket non superposé. Pour un socket non superposé, les paramètres lpOverlapped et lpCompletionRoutine sont ignorés, sauf que la fonction peut se bloquer si le socket s est en mode blocage. Si le socket s est en mode non bloquant, cette fonction sera toujours bloquée, car cette IOCTL particulière ne prend pas en charge le mode non bloquant.

Pour les sockets superposés, les opérations qui ne peuvent pas être terminées immédiatement sont lancées et l’achèvement est indiqué ultérieurement.

Toute IOCTL peut se bloquer indéfiniment, en fonction de l’implémentation du fournisseur de services. Si l’application ne peut pas tolérer le blocage dans un appel de fonction WSAIoctl ou WSPIoctl , les e/s avec chevauchement sont conseillées pour les IOCTL qui sont particulièrement susceptibles de se bloquer.

L’IOCTL de _ réservation de _ port _ SIO Acquire peut échouer avec l’opération WSAEINTR ou WSA _ _ abandonnée dans les cas suivants :

  • La demande est annulée par le gestionnaire d’e/s.
  • Le socket est fermé.

Exemples

L’exemple suivant acquiert une réservation de port d’exécution, puis crée un socket et alloue un port à partir de la réservation du port d’exécution pour le socket, puis ferme le socket et libère la réservation du port d’exécution.

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

    // 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 != 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);

            sockRes = socket(iFamily, iType, iProtocol);
            if (sockRes == INVALID_SOCKET) {
                wprintf(L"socket function for second socket failed with error = %d\n",
                        WSAGetLastError());
                closesocket(sock);
                WSACleanup();
                return 1;
            } else {
                wprintf(L"socket function for second socket succeeded\n");

                iResult =
                    WSAIoctl(sock, SIO_ASSOCIATE_PORT_RESERVATION,
                             (LPVOID) & portRes.Token, 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 = (ADDRESS_FAMILY) iFamily;
                    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));
                        }
                    }
                }
            }

            // comment out this block of code if you don't want to delete the reservation just created
            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 (sockRes != INVALID_SOCKET) {
            iResult = closesocket(sockRes);
            if (iResult == SOCKET_ERROR) {
                wprintf(L"closesocket for second socket failed with error = %d\n",
                        WSAGetLastError());
            }
        }
        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;
}

Voir aussi

accepter

établis

CreatePersistentTcpPortReservation

CreatePersistentUdpPortReservation

DeletePersistentTcpPortReservation

DeletePersistentUdpPortReservation

_étendue du port inet _

_instance de _ réservation de port inet _

LookupPersistentTcpPortReservation

LookupPersistentUdpPortReservation

_réservation de _ port SIO Associate _

_réservation de _ port de libération SIO _

socle

WSAGetLastError

WSAGetOverlappedResult

WSAIoctl

WSAOVERLAPPED

WSASocketA

WSASocketW