código de controle SIO_RELEASE_PORT_RESERVATION
Descrição
O código de controle SIO_RELEASE_PORT_RESERVATION libera uma reserva de runtime para um bloco de portas TCP ou UDP. A reserva de runtime a ser liberada deve ter sido obtida do processo de emissão usando o SIO_ACQUIRE_PORT_RESERVATION IOCTL.
Para executar essa operação, chame a função WSAIoctl ou WSPIoctl com os parâmetros a seguir.
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.
);
parâmetros
s
Um descritor que identifica um soquete.
Dwiocontrolcode
O código de controle da operação. Use SIO_RELEASE_PORT_RESERVATION para esta operação.
Lpvinbuffer
Um ponteiro para o buffer de entrada. Esse parâmetro contém um ponteiro para uma estrutura INET_PORT_RESERVATION_TOKEN com o token para a reserva de porta TCP ou UDP a ser lançada.
Cbinbuffer
O tamanho, em bytes, do buffer de entrada. Esse parâmetro deve ter pelo menos o tamanho da estrutura INET_PORT_RESERVATION_TOKEN .
Lpvoutbuffer
Um ponteiro para o buffer de saída. Esse parâmetro não é usado para essa operação.
cbOutBuffer
O tamanho, em bytes, do buffer de saída. Esse parâmetro deve ser definido como zero.
Lpcbbytesreturned
Um ponteiro para uma variável que recebe o tamanho, em bytes, dos dados armazenados no buffer de saída.
Se o buffer de saída for muito pequeno, a chamada falhará, WSAGetLastError retornará WSAEINVAL e o parâmetro lpcbBytesReturned apontará para um valor DWORD de zero.
Se lpOverlapped for NULL, o valor DWORD apontado pelo parâmetro lpcbBytesReturned retornado em uma chamada bem-sucedida não poderá ser zero.
Se o parâmetro lpOverlapped não for NULL para soquetes sobrepostos, as operações que não podem ser concluídas imediatamente serão iniciadas e a conclusão será indicada posteriormente. O valor DWORD apontado pelo parâmetro lpcbBytesReturned retornado pode ser zero, pois o tamanho dos dados armazenados não pode ser determinado até que a operação sobreposta seja concluída. O status de conclusão final pode ser recuperado quando o método de conclusão apropriado é sinalizado quando a operação é concluída.
lpvOverlapped
Um ponteiro para uma estrutura WSAOVERLAPPED .
Se o soquete s foi criado sem o atributo sobreposto, o parâmetro lpOverlapped será ignorado.
Se s foi aberto com o atributo sobreposto e o parâmetro lpOverlapped não é NULL, a operação é executada como uma operação sobreposta (assíncrona). Nesse caso, o parâmetro lpOverlapped deve apontar para uma estrutura WSAOVERLAPPED válida.
Para operações sobrepostas, a função WSAIoctl ou WSPIoctl retorna imediatamente e o método de conclusão apropriado é sinalizado quando a operação é concluída. Caso contrário, a função não retornará até que a operação seja concluída ou ocorra um erro.
Lpcompletionroutine
Tipo: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Um ponteiro para a rotina de conclusão chamado quando a operação foi concluída (ignorado para soquetes não sobrepostos).
lpThreadId
Um ponteiro para uma estrutura WSATHREADID a ser usada pelo provedor em uma chamada subsequente ao WPUQueueApc. O provedor deve armazenar a estrutura WSATHREADID referenciada (não o ponteiro para o mesmo) até que a função WPUQueueApc retorne.
Nota Esse parâmetro se aplica somente à função WSPIoctl .
Lperrno
Um ponteiro para o código de erro.
Nota Esse parâmetro se aplica somente à função WSPIoctl .
Valor retornado
Se a operação for concluída com êxito, a função WSAIoctl ou WSPIoctl retornará zero.
Se a operação falhar ou estiver pendente, a função WSAIoctl ou WSPIoctl retornará SOCKET_ERROR. Para obter informações de erro estendidas, chame WSAGetLastError.
Código do erro | Significado |
---|---|
WSA_IO_PENDING | A operação de E/S sobreposta está em andamento. Esse valor será retornado se uma operação sobreposta tiver sido iniciada com êxito e a conclusão for indicada posteriormente. |
WSA_OPERATION_ABORTED | A operação de E/S foi anulada devido ao encerramento de um thread ou a uma solicitação de aplicativo. Esse erro será retornado se uma operação sobreposta tiver sido cancelada devido ao fechamento do soquete ou à execução do comando SIO_FLUSH IOCTL. |
WSAEFAULT | O sistema detectou um endereço de ponteiro inválido ao tentar usar um argumento de ponteiro em uma chamada. Esse erro é retornado do parâmetro lpOverlapped ou lpCompletionRoutine não está totalmente contido em uma parte válida do espaço de endereço do usuário. |
WSAEINPROGRESS | Uma operação de bloqueio está atualmente em execução. Esse erro será retornado se a função for invocada quando um retorno de chamada estiver em andamento. |
WSAEINTR | Uma operação de bloqueio foi interrompida por uma chamada para WSACancelBlockingCall. Esse erro será retornado se uma operação de bloqueio tiver sido interrompida. |
WSAEINVAL | Foi fornecido um argumento inválido. Esse erro será retornado se o parâmetro dwIoControlCode não for um comando válido ou um parâmetro de entrada especificado não for aceitável ou o comando não for aplicável ao tipo de soquete especificado. |
WSAENETDOWN | Uma operação de soquete encontrou uma rede inoperante. Esse erro será retornado se o subsistema de rede falhar. |
WSAENOTSOCK | Uma operação foi tentada em algo que não é um soquete. Esse erro será retornado se o descritor não for um soquete. |
WSAEOPNOTSUPP | Não há suporte para a tentativa de operação para o tipo de objeto referenciado. Esse erro será retornado se o comando IOCTL especificado não tiver suporte. Esse erro também será retornado se o SIO_RELEASE_PORT_RESERVATION IOCTL não tiver suporte do provedor de transporte. Esse erro também é retornado quando uma tentativa de usar o SIO_RELEASE_PORT_RESERVATION IOCTL é feita em um soquete diferente de UDP ou TCP. |
Comentários
O SIO_RELEASE_PORT_RESERVATION IOCTL tem suporte em Windows Vista e versões posteriores do sistema operacional.
Aplicativos e serviços que precisam reservar portas se enquadram em duas categorias. A primeira categoria inclui componentes que precisam de uma porta específica como parte de sua operação. Esses componentes geralmente preferem especificar a porta necessária no momento da instalação (em um manifesto do aplicativo, por exemplo). A segunda categoria inclui componentes que precisam de qualquer porta disponível ou bloco de portas em runtime. Essas duas categorias correspondem a solicitações de reserva de porta específicas e curinga. Solicitações de reserva específicas podem ser persistentes ou runtime, enquanto as solicitações de reserva de porta curinga só têm suporte no runtime.
O SIO_ACQUIRE_PORT_RESERVATION IOCTL é usado para solicitar uma reserva de runtime para um bloco de portas TCP ou UDP. Para reservas de porta de runtime, o pool de portas exige que as reservas sejam consumidas do processo em cujo soquete a reserva foi concedida. As reservas de porta de runtime duram apenas o tempo de vida do soquete no qual o SIO_ACQUIRE_PORT_RESERVATION IOCTL foi chamado. Por outro lado, as reservas de porta persistentes criadas usando a função CreatePersistentTcpPortReservation ou CreatePersistentUdpPortReservation podem ser consumidas por qualquer processo com a capacidade de obter reservas persistentes.
O SIO_RELEASE_PORT_RESERVATION IOCTL é usado para liberar uma reserva de runtime para um bloco de portas TCP ou UDP.
Se os parâmetros lpOverlapped e lpCompletionRoutine forem NULL, o soquete nessa função será tratado como um soquete não sobreposto. Para um soquete não sobreposto, os parâmetros lpOverlapped e lpCompletionRoutine são ignorados, exceto que a função pode bloquear se o soquete s estiver no modo de bloqueio. Se o soquete estiver no modo sem bloqueio, essa função ainda será bloqueada, pois esse IOCTL específico não dá suporte ao modo de não bloqueio.
Para soquetes sobrepostos, as operações que não podem ser concluídas imediatamente serão iniciadas e a conclusão será indicada posteriormente.
Qualquer IOCTL pode ser bloqueada indefinidamente, dependendo da implementação do provedor de serviços. Se o aplicativo não puder tolerar o bloqueio em uma chamada de função WSAIoctl ou WSPIoctl , a E/S sobreposta será aconselhada para IOCTLs que são especialmente propensas a serem bloqueadas.
O SIO_RELEASE_PORT_RESERVATION IOCTL pode falhar com WSAEINTR ou WSA_OPERATION_ABORTED nos seguintes casos:
- A solicitação é cancelada pelo Gerenciador de E/S.
- O soquete está fechado.
Exemplos
O exemplo a seguir adquire uma reserva de porta de runtime e libera a reserva de porta de 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;
}
Confira também
CreatePersistentTcpPortReservation
CreatePersistentUdpPortReservation
DeletePersistentTcpPortReservation
DeletePersistentUdpPortReservation
LookupPersistentTcpPortReservation
LookupPersistentUdpPortReservation