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
入力バッファーへのポインター。 このパラメーターには、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 構造体へのポインター。
重複する属性なしでソケット s が作成された場合、 lpOverlapped パラメーターは無視されます。
重複した属性を使用して s を開き、 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 | ソケットではない操作が試行されました。 記述子 s がソケットでない場合、このエラーが返されます。 |
WSAEOPNOTSUPP | 試行された操作は、参照されるオブジェクトの種類ではサポートされていません。 このエラーは、指定された IOCTL コマンドがサポートされていない場合に返されます。 このエラーは、 SIO_RELEASE_PORT_RESERVATION IOCTL がトランスポート プロバイダーでサポートされていない場合にも返されます。 このエラーは、UDP または TCP 以外のソケットで SIO_RELEASE_PORT_RESERVATION IOCTL を使用しようとするとも返されます。 |
注釈
SIO_RELEASE_PORT_RESERVATION IOCTL は、Windows Vista 以降のバージョンのオペレーティング システムでサポートされています。
ポートを予約する必要があるアプリケーションとサービスは、2 つのカテゴリに分類されます。 最初のカテゴリには、操作の一部として特定のポートを必要とするコンポーネントが含まれています。 このようなコンポーネントは、通常、インストール時に必要なポートを指定することを好みます (たとえば、アプリケーション マニフェストで)。 2 番目のカテゴリには、実行時に使用可能なポートまたはポート ブロックが必要なコンポーネントが含まれています。 これら 2 つのカテゴリは、特定のポート予約要求とワイルドカード ポート予約要求に対応しています。 特定の予約要求は永続的または実行時である場合があります。一方、ワイルドカード ポート予約要求は実行時にのみサポートされます。
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 パラメーターは無視されます。ただし、ソケット s がブロック モードの場合、関数はブロックできます。 ソケット s が非ブロッキング モードの場合、この特定の 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