Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Функция 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.
Если функция завершается сбоем, возвращается один из следующих кодов ошибок.
| Код возврата | Описание |
|---|---|
|
Отказано в доступе". Эта ошибка возвращается при нескольких условиях, которые включают следующее: у пользователя отсутствуют необходимые права администратора на локальном компьютере или приложение не работает в расширенной оболочке в качестве встроенного администратора (администратор запуска от имени администратора). |
|
В функцию передан недопустимый параметр.
Эта ошибка возвращается, если в параметрах StartPort или NumberOfPorts передается ноль. Эта ошибка также возвращается, если параметр NumberOfPorts слишком велик на блок портов в зависимости от параметра StartPort , что выделенный блок портов превысит максимальное количество портов, которое может быть выделено. |
|
The process cannot access the file because it is being used by another process. Эта ошибка возвращается, если TCP-порт в блоке TCP-портов, указанных параметрами StartPort и NumberOfPorts , уже используется. Эта ошибка также возвращается, если постоянное резервирование для блока TCP-портов, указанных параметрами StartPort и NumberOfPorts , совпадает или перекрывает постоянное резервирование для уже созданного блока TCP-портов. |
|
Используйте FormatMessage , чтобы получить строку сообщения для возвращаемой ошибки. |
Комментарии
Функция CreatePersistentTcpPortReservation определена в Windows Vista и более поздних версиях.
Функция CreatePersistentTcpPortReservation используется для добавления постоянного резервирования для блока TCP-портов.
Приложения и службы, которым необходимо зарезервировать порты, делятся на две категории. Первая категория включает компоненты, которым требуется определенный порт в рамках операции. Такие компоненты обычно предпочитают указывать необходимый порт во время установки (например, в манифесте приложения). Вторая категория включает компоненты, которым требуется любой доступный порт или блок портов во время выполнения.
Эти две категории соответствуют конкретным запросам на резервирование портов и с подстановочными знаками. Определенные запросы на резервирование могут быть постоянными или выполняться во время выполнения, а запросы на резервирование портов с подстановочными знаками поддерживаются только во время выполнения.
Функция CreatePersistentTcpPortReservation позволяет приложению или службе резервировать постоянный блок TCP-портов. Постоянные резервирования TCP-портов записываются в постоянное хранилище для модуля TCP в Windows.
Вызывающий объект получает постоянное резервирование портов, указывая, сколько портов требуется и требуется ли определенный диапазон. Если запрос может быть удовлетворен, функция CreatePersistentTcpPortReservation возвращает уникальный непрозрачный маркер ULONG64, который впоследствии идентифицирует резервирование. Постоянное резервирование TCP-портов можно освободить, вызвав функцию DeletePersistentTcpPortReservation . Обратите внимание, что маркер для заданного постоянного резервирования TCP-порта может изменяться при каждом перезапуске системы.
Windows не реализует межкомпонентную безопасность для постоянных резервирований, полученных с помощью этих функций. Это означает, что если компоненту предоставляется возможность получать постоянные резервирования портов, этот компонент автоматически получает возможность использовать все постоянные резервирования портов, предоставленные любому другому компоненту в системе. Безопасность на уровне процесса применяется для резервирований среды выполнения, но такое управление не может быть расширено на постоянные резервирования портов, созданные с помощью функции CreatePersistentTcpPortReservation или CreatePersistentUdpPortReservation .
После получения постоянного резервирования TCP-порта приложение может запросить назначения портов из резервирования TCP-портов, открыв сокет TCP, а затем вызвав функцию WSAIoctl , указав SIO_ASSOCIATE_PORT_RESERVATION IOCTL и передав маркер резервирования перед вызовом функции bind в сокете.
SIO_ACQUIRE_PORT_RESERVATION IOCTL можно использовать для запроса резервирования среды выполнения для блока портов TCP или UDP. Для резервирования портов среды выполнения пул портов требует, чтобы резервирования были использованы из процесса, в сокете которого было предоставлено резервирование. Резервирование портов среды выполнения выполняется только до тех пор, пока время существования сокета, в котором был вызван SIO_ACQUIRE_PORT_RESERVATION IOCTL. В отличие от этого, резервирования постоянных портов, созданные с помощью функции CreatePersistentTcpPortReservation , могут использоваться любым процессом с возможностью получения постоянных резервирований.
Функция CreatePersistentTcpPortReservation может вызываться только пользователем, вошедшего в систему как член группы администраторов. Если метод CreatePersistentTcpPortReservation вызывается пользователем, не включаемым в группу Администраторы, вызов функции завершится ошибкой и возвращается ERROR_ACCESS_DENIED . Эта функция также может завершиться сбоем из-за контроля учетных записей (UAC) в Windows Vista и более поздних версиях. Если приложение, содержащее эту функцию, выполняется пользователем, вошедшего в систему как член группы администраторов, отличный от встроенного администратора, этот вызов завершится ошибкой, если приложение не было отмечено в файле манифеста с параметром requestedExecutionLevel , для которого задано значение requireAdministrator. Если в приложении отсутствует этот файл манифеста, пользователь, вошедший в систему как член группы администраторов, отличный от встроенного администратора, должен выполнить приложение в расширенной оболочке в качестве встроенного администратора (администратора запуска от имени), чтобы эта функция была успешной.
Примеры
В следующем примере создается постоянное резервирование TCP-портов, затем создается сокет и выделяется порт из резервирования портов, а затем закрывается сокет и удаляется резервирование TCP-порта.
Этот пример должен выполнять пользователь, который является членом группы "Администраторы". Самый простой способ запустить этот пример — в расширенной оболочке в качестве встроенного администратора (администратор запуска от имени).
#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 |
| Header | iphlpapi.h |
| Библиотека | Iphlpapi.lib |
| DLL | Iphlpapi.dll |
См. также раздел
CreatePersistentUdpPortReservation
DeletePersistentTcpPortReservation
DeletePersistentUdpPortReservation
LookupPersistentTcpPortReservation
LookupPersistentUdpPortReservation