CreatePersistentTcpPortReservation 함수(iphlpapi.h)
CreatePersistentTcpPortReservation 함수는 로컬 컴퓨터에서 연속된 TCP 포트 블록에 대한 영구 TCP 포트 예약을 만듭니다.
구문
IPHLPAPI_DLL_LINKAGE ULONG CreatePersistentTcpPortReservation(
[in] USHORT StartPort,
[in] USHORT NumberOfPorts,
[out] PULONG64 Token
);
매개 변수
[in] StartPort
네트워크 바이트 순서의 시작 TCP 포트 번호입니다.
[in] NumberOfPorts
예약할 TCP 포트 번호의 수입니다.
[out] Token
함수가 성공하면 반환되는 포트 예약 토큰에 대한 포인터입니다.
반환 값
함수가 성공하면 반환 값이 NO_ERROR.
함수가 실패하면 반환 값은 다음 오류 코드 중 하나입니다.
반환 코드 | 설명 |
---|---|
|
액세스가 거부되었습니다. 이 오류는 다음을 포함하는 여러 조건에서 반환됩니다. 사용자가 로컬 컴퓨터에 필요한 관리 권한이 없거나 애플리케이션이 기본 제공 관리자(RunAs 관리자)로 향상된 셸에서 실행되고 있지 않습니다. |
|
잘못된 매개 변수가 함수에 전달되었습니다.
StartPort 또는NumberOfPorts 매개 변수에 0이 전달되면 이 오류가 반환됩니다. 이 오류는 NumberOfPorts 매개 변수가 할당 가능한 포트 블록이 할당할 수 있는 최대 포트를 초과하는 StartPort 매개 변수에 따라 포트 블록이 너무 큰 경우에도 반환됩니다. |
|
다른 프로세스가 파일을 사용 중이기 때문에 프로세스가 액세스할 수 없습니다. StartPort 및 NumberOfPorts 매개 변수로 지정된 TCP 포트 블록의 TCP 포트가 이미 사용 중인 경우 이 오류가 반환됩니다. StartPort 및 NumberOfPorts 매개 변수로 지정된 TCP 포트 블록에 대한 영구 예약이 이미 생성된 TCP 포트 블록에 대한 영구 예약과 일치하거나 겹치는 경우에도 이 오류가 반환됩니다. |
|
FormatMessage를 사용하여 반환된 오류에 대한 메시지 문자열을 가져옵니다. |
설명
CreatePersistentTcpPortReservation 함수는 Windows Vista 이상에서 정의됩니다.
CreatePersistentTcpPortReservation 함수는 TCP 포트 블록에 대한 영구 예약을 추가하는 데 사용됩니다.
포트를 예약해야 하는 애플리케이션 및 서비스는 두 가지 범주로 구분됩니다. 첫 번째 범주에는 작업의 일부로 특정 포트가 필요한 구성 요소가 포함됩니다. 이러한 구성 요소는 일반적으로 설치 시 필요한 포트를 지정하는 것을 선호합니다(예: 애플리케이션 매니페스트에서). 두 번째 범주에는 런타임에 사용 가능한 포트 또는 포트 블록이 필요한 구성 요소가 포함됩니다.
이러한 두 범주는 특정 및 와일드카드 포트 예약 요청에 해당합니다. 특정 예약 요청은 영구 또는 런타임일 수 있지만 와일드카드 포트 예약 요청은 런타임에만 지원됩니다.
CreatePersistentTcpPortReservation 함수는 애플리케이션 또는 서비스가 TCP 포트의 영구 블록을 예약하는 기능을 제공합니다. 영구 TCP 포트 예약은 Windows의 TCP 모듈에 대한 영구 저장소에 기록됩니다.
호출자는 필요한 포트 수와 특정 범위가 필요한지 여부를 지정하여 영구 포트 예약을 가져옵니다. 요청을 충족할 수 있는 경우 CreatePersistentTcpPortReservation 함수는 이후에 예약을 식별하는 고유한 불투명 ULONG64 토큰을 반환합니다. DeletePersistentTcpPortReservation 함수를 호출하여 영구 TCP 포트 예약을 해제할 수 있습니다. 지정된 영구 TCP 포트 예약에 대한 토큰은 시스템을 다시 시작할 때마다 변경될 수 있습니다.
Windows는 이러한 함수를 사용하여 얻은 영구 예약에 대해 구성 요소 간 보안을 구현하지 않습니다. 즉, 구성 요소에 영구 포트 예약을 가져올 수 있는 기능이 부여되면 해당 구성 요소는 시스템의 다른 구성 요소에 부여된 영구 포트 예약을 자동으로 사용할 수 있습니다. 프로세스 수준 보안은 런타임 예약에 적용되지만 이러한 제어는 CreatePersistentTcpPortReservation 또는 CreatePersistentUdpPortReservation 함수를 사용하여 만든 영구 포트 예약으로 확장할 수 없습니다.
영구 TCP 포트 예약이 확보되면 애플리케이션은 TCP 소켓을 연 다음, WSAIoctl 함수를 호출하여 TCP 포트 예약에서 포트 할당을 요청할 수 있으며, SIO_ASSOCIATE_PORT_RESERVATION IOCTL을 지정하고 소켓에서 바인딩 함수에 대한 호출을 실행하기 전에 예약 토큰을 전달할 수 있습니다.
SIO_ACQUIRE_PORT_RESERVATION IOCTL을 사용하여 TCP 또는 UDP 포트 블록에 대한 런타임 예약을 요청할 수 있습니다. 런타임 포트 예약의 경우 포트 풀은 예약이 부여된 소켓의 프로세스에서 예약을 사용해야 합니다. 런타임 포트 예약은 SIO_ACQUIRE_PORT_RESERVATION IOCTL이 호출된 소켓의 수명 동안만 지속됩니다. 반면, CreatePersistentTcpPortReservation 함수를 사용하여 만든 영구 포트 예약은 영구 예약을 가져올 수 있는 모든 프로세스에서 사용될 수 있습니다.
CreatePersistentTcpPortReservation 함수는 관리자 그룹의 구성원으로 로그온한 사용자만 호출할 수 있습니다. Administrators 그룹의 구성원이 아닌 사용자가 CreatePersistentTcpPortReservation 을 호출하면 함수 호출이 실패하고 ERROR_ACCESS_DENIED 반환됩니다. 이 함수는 Windows Vista 이상에서 UAC(사용자 계정 제어)로 인해 실패할 수도 있습니다. 이 함수를 포함하는 애플리케이션이 기본 제공 관리자가 아닌 Administrators 그룹의 구성원으로 로그온한 사용자에 의해 실행되는 경우 애플리케이션이 requestedExecutionLevel 이 requireAdministrator로 설정된 매니페스트 파일에 표시되지 않는 한 이 호출은 실패합니다. 애플리케이션에 이 매니페스트 파일이 없는 경우 기본 제공 관리자가 아닌 Administrators 그룹의 구성원으로 로그온한 사용자는 이 함수가 성공하려면 기본 제공 관리자(RunAs 관리자)로 향상된 셸에서 애플리케이션을 실행해야 합니다.
예제
다음 예제에서는 영구 TCP 포트 예약을 만든 다음 소켓을 만들고 포트 예약에서 포트를 할당한 다음 소켓을 닫고 TCP 포트 예약을 삭제합니다.
이 예제는 Administrators 그룹의 구성원인 사용자가 실행해야 합니다. 이 예제를 실행하는 가장 간단한 방법은 향상된 셸에서 기본 제공 관리자(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;
}
요구 사항
요구 사항 | 값 |
---|---|
지원되는 최소 클라이언트 | Windows Vista [데스크톱 앱만 해당] |
지원되는 최소 서버 | Windows Server 2008 [데스크톱 앱만 해당] |
대상 플랫폼 | Windows |
헤더 | iphlpapi.h |
라이브러리 | Iphlpapi.lib |
DLL | Iphlpapi.dll |
추가 정보
CreatePersistentUdpPortReservation
DeletePersistentTcpPortReservation
DeletePersistentUdpPortReservation
LookupPersistentTcpPortReservation
LookupPersistentUdpPortReservation