Код элемента управления 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.
);
Параметры
s
Дескриптор, определяющий сокет.
dwIoControlCode
Код элемента управления для операции. Для этой операции используйте SIO_RELEASE_PORT_RESERVATION .
lpvInBuffer
Указатель на входной буфер. Этот параметр содержит указатель на структуру INET_PORT_RESERVATION_TOKEN с маркером для освобождения резервирования портов TCP или UDP.
cbInBuffer
Размер входного буфера (в байтах). Этот параметр должен быть не ниже размера структуры INET_PORT_RESERVATION_TOKEN .
lpvOutBuffer
Указатель на выходной буфер. Этот параметр не используется для этой операции.
cbOutBuffer
Размер выходного буфера (в байтах). Этот параметр должен иметь нулевое значение.
lpcbBytesReturned
Указатель на переменную, которая получает размер данных в байтах, хранящихся в выходном буфере.
Если выходной буфер слишком мал, вызов завершается ошибкой, WSAGetLastError возвращает WSAEINVAL, а параметр lpcbBytesReturned указывает на значение DWORD , равное нулю.
Если lpOverlapped имеет значение NULL, значение DWORD , на которое указывает параметр lpcbBytesReturned , возвращаемое при успешном вызове, не может быть равным нулю.
Если параметр lpOverlapped не имеет значения NULL для перекрывающихся сокетов, операции, которые не могут быть завершены немедленно, будут инициированы, а завершение будет указано позже. Значение DWORD , на которое указывает возвращаемый параметр lpcbBytesReturned , может быть равным нулю, так как размер хранимых данных не может быть определен до завершения перекрывающейся операции. Окончательное состояние завершения можно получить, когда соответствующий метод завершения получает сигнал о завершении операции.
lpvOverlapped
Указатель на структуру WSAOVERLAPPED .
Если сокеты были созданы без перекрывающихся атрибутов, параметр lpOverlapped игнорируется.
Если объект был открыт с перекрывающимся атрибутом, а параметр lpOverlapped не имеет значения NULL, операция выполняется как перекрываемая (асинхронная) операция. В этом случае параметр lpOverlapped должен указывать на допустимую структуру WSAOVERLAPPED .
Для перекрывающихся операций функция WSAIoctl или WSPIoctl возвращается немедленно, а соответствующий метод завершения получает сигнал о завершении операции. В противном случае функция не возвращается, пока операция не будет завершена или не возникнет ошибка.
lpCompletionRoutine
Тип: _In_opt_ LPWSAOVERLAPPED_COMPLETION_ROUTINE
Указатель на подпрограмму завершения, вызываемую при завершении операции (игнорируется для неперекрывающихся сокетов).
lpThreadId
Указатель на структуру WSATHREADID , которая будет использоваться поставщиком при последующем вызове WPUQueueApc. Поставщик должен хранить указанную структуру WSATHREADID (а не указатель на нее) до тех пор, пока не будет возвращена функция WPUQueueApc .
Примечание Этот параметр применяется только к функции WSPIoctl .
lpErrno
Указатель на код ошибки.
Примечание Этот параметр применяется только к функции WSPIoctl .
Возвращаемое значение
Если операция завершается успешно, функция WSAIoctl или WSPIoctl возвращает ноль.
Если операция завершается сбоем или находится в состоянии ожидания, функция WSAIoctl или WSPIoctl возвращает SOCKET_ERROR. Чтобы получить расширенные сведения об ошибке, вызовите WSAGetLastError.
Код ошибки | Значение |
---|---|
WSA_IO_PENDING | Выполняется перекрываемая операция ввода-вывода. Это значение возвращается, если перекрываемая операция была успешно инициирована, а завершение будет указано позже. |
WSA_OPERATION_ABORTED | Операция ввода-вывода прекращена из-за выхода из потока или запроса приложения. Эта ошибка возвращается, если перекрываемая операция была отменена из-за закрытия сокета или выполнения команды IOCTL SIO_FLUSH . |
WSAEFAULT | Система обнаружила недопустимый адрес указателя при попытке использовать аргумент указателя в вызове. Эта ошибка возвращается из параметра lpOverlapped или lpCompletionRoutine не полностью содержится в допустимой части адресного пространства пользователя. |
WSAEINPROGRESS | В данный момент выполняется блокирующая операция. Эта ошибка возвращается, если функция вызывается при выполнении обратного вызова. |
WSAEINTR | Операция блокировки была прервана вызовом WSACancelBlockingCall. Эта ошибка возвращается, если операция блокировки была прервана. |
WSAEINVAL | Указан недопустимый аргумент. Эта ошибка возвращается, если параметр dwIoControlCode не является допустимой командой, если указанный входной параметр недопустим или команда не применима к указанному типу сокета. |
WSAENETDOWN | Операция на сокете обнаружила отключение сети. Эта ошибка возвращается в случае сбоя сетевой подсистемы. |
WSAENOTSOCK | Предпринята попытка выполнить операцию с тем, что не является сокетом. Эта ошибка возвращается, если дескриптор не является сокетом. |
WSAEOPNOTSUPP | Предпринятая операция не поддерживается для типа объекта, на который указывает ссылка. Эта ошибка возвращается, если указанная команда IOCTL не поддерживается. Эта ошибка также возвращается, если поставщик транспорта не поддерживает SIO_RELEASE_PORT_RESERVATION IOCTL. Эта ошибка также возвращается при попытке использовать SIO_RELEASE_PORT_RESERVATION IOCTL в сокете, отличном от UDP или TCP. |
Комментарии
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, которые особенно вероятно, будут блокироваться перекрывающиеся операции ввода-вывода.
Сбой SIO_RELEASE_PORT_RESERVATION IOCTL с помощью WSAEINTR или WSA_OPERATION_ABORTED в следующих случаях:
- Запрос отменяется диспетчером ввода-вывода.
- Сокет закрыт.
Примеры
В следующем примере выполняется получение резервирования портов среды выполнения, а затем освобождение резервирования портов среды выполнения.
#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