SIO_RELEASE_PORT_RESERVATION 제어 코드
설명
SIO_RELEASE_PORT_RESERVATION 제어 코드는 TCP 또는 UDP 포트 블록에 대한 런타임 예약을 해제합니다. 릴리스할 런타임 예약은 SIO_ACQUIRE_PORT_RESERVATION IOCTL을 사용하여 발급 프로세스에서 가져와야 합니다.
이 작업을 수행하려면 다음 매개 변수를 사용하여 WSAIoctl 또는 WSPIoctl 함수를 호출합니다.
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.
);
매개 변수
초
소켓을 식별하는 설명자입니다.
dwIoControlCode
작업을 위한 제어 코드입니다. 이 작업에 는 SIO_RELEASE_PORT_RESERVATION 사용합니다.
lpvInBuffer
입력 버퍼에 대한 포인터입니다. 이 매개 변수에는 해제할 TCP 또는 UDP 포트 예약에 대한 토큰이 있는 INET_PORT_RESERVATION_TOKEN 구조체에 대한 포인터가 포함되어 있습니다.
cbInBuffer
입력 버퍼의 크기(바이트)입니다. 이 매개 변수는 INET_PORT_RESERVATION_TOKEN 구조체의 크기 이상이어야 합니다.
lpvOutBuffer
출력 버퍼에 대한 포인터입니다. 이 매개 변수는 이 작업에 사용되지 않습니다.
cbOutBuffer
출력 버퍼의 크기(바이트)입니다. 이 매개 변수는 0으로 설정해야 합니다.
lpcbBytesReturned
출력 버퍼에 저장된 데이터의 크기(바이트)를 수신하는 변수에 대한 포인터입니다.
출력 버퍼가 너무 작으면 호출이 실패하고 WSAGetLastError 가 WSAEINVAL을 반환하고 lpcbBytesReturned 매개 변수가 DWORD 값 0을 가리킵니다.
lpOverlapped가 NULL이면 성공적인 호출에서 반환되는 lpcbBytesReturned 매개 변수가 가리키는 DWORD 값은 0일 수 없습니다.
lpOverlapped 매개 변수가 겹치는 소켓에 대해 NULL이 아닌 경우 즉시 완료할 수 없는 작업이 시작되고 나중에 완료가 표시됩니다. 겹치는 작업이 완료될 때까지 저장된 데이터의 크기를 확인할 수 없으므로 반환되는 lpcbBytesReturned 매개 변수가 가리키는 DWORD 값은 0일 수 있습니다. 작업이 완료되었을 때 적절한 완료 메서드가 신호를 받으면 최종 완료 상태 검색할 수 있습니다.
lpvOverlapped
WSAOVERLAPPED 구조체에 대한 포인터입니다.
겹치는 특성 없이 소켓 을 만든 경우 lpOverlapped 매개 변수는 무시됩니다.
가 겹치는 특성으로 열렸고 lpOverlapped 매개 변수가 NULL이 아닌 경우 작업은 겹치는(비동기) 작업으로 수행됩니다. 이 경우 lpOverlapped 매개 변수는 유효한 WSAOVERLAPPED 구조를 가리킵니다.
겹치는 작업의 경우 WSAIoctl 또는 WSPIoctl 함수가 즉시 반환되고 작업이 완료되면 적절한 완료 메서드가 신호를 보냅니다. 그렇지 않으면 작업이 완료되거나 오류가 발생할 때까지 함수가 반환되지 않습니다.
lpCompletionRoutine
형식: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
작업이 완료될 때 호출되는 완료 루틴에 대한 포인터입니다(겹치지 않는 소켓의 경우 무시됨).
lpThreadId
WPUQueueApc에 대한 후속 호출에서 공급자가 사용할 WSATHREADID 구조체에 대한 포인터입니다. 공급자는 WPUQueueApc 함수가 반환될 때까지 참조된 WSATHREADID 구조체(동일한 포인터가 아님)를 저장해야 합니다.
참고 이 매개 변수는 WSPIoctl 함수에 만 적용됩니다.
lpErrno
오류 코드에 대한 포인터입니다.
참고 이 매개 변수는 WSPIoctl 함수에 만 적용됩니다.
반환 값
작업이 성공적으로 완료되면 WSAIoctl 또는 WSPIoctl 함수는 0을 반환합니다.
작업이 실패하거나 보류 중인 경우 WSAIoctl 또는 WSPIoctl 함수는 SOCKET_ERROR 반환합니다. 확장 오류 정보를 얻으려면 WSAGetLastError를 호출합니다.
오류 코드 | 의미 |
---|---|
WSA_IO_PENDING | 중첩된 I/O 작업이 진행 중입니다. 겹치는 작업이 성공적으로 시작되고 나중에 완료가 표시되면 이 값이 반환됩니다. |
WSA_OPERATION_ABORTED | 스레드 종료 또는 애플리케이션 요청으로 인해 I/O 작업이 중단되었습니다. 이 오류는 소켓의 닫기 또는 SIO_FLUSH IOCTL 명령 실행으로 인해 겹치는 작업이 취소된 경우 반환됩니다. |
WSAEFAULT | 시스템이 호출에서 포인터 인수를 사용하려는 시도에서 잘못된 포인터 주소를 발견했습니다. 이 오류는 lpOverlapped 또는 lpCompletionRoutine 매개 변수가 사용자 주소 공간의 유효한 부분에 완전히 포함되지 않은 경우에 반환됩니다. |
WSAEINPROGRESS | 차단 작업이 진행 중입니다. 이 오류는 콜백이 진행 중일 때 함수가 호출되는 경우 반환됩니다. |
WSAEINTR | WSACancelBlockingCall 호출로 인해 차단 작업이 중단되었습니다. 차단 작업이 중단된 경우 이 오류가 반환됩니다. |
WSAEINVAL | 잘못된 인수가 지정되었습니다. 이 오류는 dwIoControlCode 매개 변수가 유효한 명령이 아니거나 지정된 입력 매개 변수가 허용되지 않거나 명령이 지정된 소켓 형식에 적용되지 않는 경우 반환됩니다. |
WSAENETDOWN | 소켓 작업에서 작동하지 않는 네트워크가 검색되었습니다. 이 오류는 네트워크 하위 시스템이 실패한 경우 반환됩니다. |
WSAENOTSOCK | 소켓이 아닌 항목에서 작업을 시도했습니다. 설명 자가 소 켓이 아닌 경우 이 오류가 반환됩니다. |
WSAEOPNOTSUPP | 시도한 작업은 참조된 개체 형식에 대해 지원되지 않습니다. 지정된 IOCTL 명령이 지원되지 않는 경우 이 오류가 반환됩니다. 이 오류는 전송 공급자가 SIO_RELEASE_PORT_RESERVATION IOCTL을 지원하지 않는 경우에도 반환됩니다. 이 오류는 UDP 또는 TCP 이외의 소켓에서 SIO_RELEASE_PORT_RESERVATION IOCTL을 사용하려고 할 때도 반환됩니다. |
설명
SIO_RELEASE_PORT_RESERVATION IOCTL은 Windows Vista 이상 버전의 운영 체제에서 지원됩니다.
포트를 예약해야 하는 애플리케이션 및 서비스는 두 가지 범주로 구분됩니다. 첫 번째 범주에는 작업의 일부로 특정 포트가 필요한 구성 요소가 포함됩니다. 이러한 구성 요소는 일반적으로 설치 시 필요한 포트를 지정하는 것을 선호합니다(예: 애플리케이션 매니페스트). 두 번째 범주에는 런타임에 사용 가능한 포트 또는 포트 블록이 필요한 구성 요소가 포함됩니다. 이러한 두 범주는 특정 및 와일드카드 포트 예약 요청에 해당합니다. 특정 예약 요청은 영구 또는 런타임일 수 있지만 와일드카드 포트 예약 요청은 런타임에만 지원됩니다.
SIO_ACQUIRE_PORT_RESERVATION IOCTL은 TCP 또는 UDP 포트 블록에 대한 런타임 예약을 요청하는 데 사용됩니다. 런타임 포트 예약의 경우 포트 풀은 예약이 부여된 소켓의 프로세스에서 예약을 사용해야 합니다. 런타임 포트 예약은 SIO_ACQUIRE_PORT_RESERVATION IOCTL이 호출된 소켓의 수 명 동안만 지속됩니다. 반면, CreatePersistentTcpPortReservation 또는 CreatePersistentUdpPortReservation 함수를 사용하여 만든 영구 포트 예약은 영구 예약을 가져올 수 있는 모든 프로세스에서 사용할 수 있습니다.
SIO_RELEASE_PORT_RESERVATION IOCTL은 TCP 또는 UDP 포트 블록에 대한 런타임 예약을 해제하는 데 사용됩니다.
lpOverlapped 및 lpCompletionRoutine 매개 변수가 모두 NULL인 경우 이 함수의 소켓은 겹치지 않는 소켓으로 처리됩니다. 겹치지 않는 소켓의 경우 lpOverlapped 및 lpCompletionRoutine 매개 변수는 무시됩니다. 단, 소켓 이 차단 모드인 경우 함수가 차단할 수 있습니다. 소켓 이 비블로킹 모드인 경우 이 특정 IOCTL은 비블로킹 모드를 지원하지 않으므로 이 함수는 여전히 차단됩니다.
겹치는 소켓의 경우 즉시 완료할 수 없는 작업이 시작되고 나중에 완료가 표시됩니다.
모든 IOCTL은 서비스 공급자의 구현에 따라 무기한 차단할 수 있습니다. 애플리케이션이 WSAIoctl 또는 WSPIoctl 함수 호출에서 차단을 허용할 수 없는 경우 특히 차단할 가능성이 있는 IOCTL 에 대해 겹치는 I/O를 권장합니다.
SIO_RELEASE_PORT_RESERVATION IOCTL은 WSAEINTR로 실패하거나 다음 경우에 WSA_OPERATION_ABORTED 수 있습니다.
- 요청은 I/O 관리자에 의해 취소됩니다.
- 소켓이 닫혔습니다.
예제
다음 예제에서는 런타임 포트 예약을 획득한 다음 런타임 포트 예약을 해제합니다.
#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;
}
추가 정보
CreatePersistentTcpPortReservation
CreatePersistentUdpPortReservation
DeletePersistentTcpPortReservation
DeletePersistentUdpPortReservation
LookupPersistentTcpPortReservation
LookupPersistentUdpPortReservation