Kode Kontrol SIO_RELEASE_PORT_RESERVATION
Deskripsi
Kode kontrol SIO_RELEASE_PORT_RESERVATION merilis reservasi runtime untuk blok port TCP atau UDP. Reservasi runtime yang akan dirilis harus diperoleh dari proses penerbitan menggunakan SIO_ACQUIRE_PORT_RESERVATION IOCTL.
Untuk melakukan operasi ini, panggil fungsi WSAIoctl atau WSPIoctl dengan parameter berikut.
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.
);
Parameter
s
Deskriptor yang mengidentifikasi soket.
dwIoControlCode
Kode kontrol untuk operasi. Gunakan SIO_RELEASE_PORT_RESERVATION untuk operasi ini.
lpvInBuffer
Penunjuk ke buffer input. Parameter ini berisi pointer ke struktur INET_PORT_RESERVATION_TOKEN dengan token untuk rilis reservasi port TCP atau UDP.
cbInBuffer
Ukuran, dalam byte, dari buffer input. Parameter ini harus setidaknya ukuran struktur INET_PORT_RESERVATION_TOKEN .
lpvOutBuffer
Penunjuk ke buffer output. Parameter ini tidak digunakan untuk operasi ini.
cbOutBuffer
Ukuran, dalam byte, dari buffer output. Parameter ini harus diatur ke nol.
lpcbBytesReturned
Penunjuk ke variabel yang menerima ukuran, dalam byte, dari data yang disimpan dalam buffer output.
Jika buffer output terlalu kecil, panggilan gagal, WSAGetLastError mengembalikan WSAEINVAL, dan parameter lpcbBytesReturned menunjuk ke nilai DWORD nol.
Jika lpOverlapped adalah NULL, nilai DWORD yang ditunjukkan oleh parameter lpcbBytesReturned yang dikembalikan pada panggilan yang berhasil tidak boleh nol.
Jika parameter lpOverlapped bukan NULL untuk soket yang tumpang tindih, operasi yang tidak dapat segera diselesaikan akan dimulai, dan penyelesaian akan ditunjukkan di lain waktu. Nilai DWORD yang ditunjukkan oleh parameter lpcbBytesReturned yang dikembalikan mungkin nol karena ukuran data yang disimpan tidak dapat ditentukan sampai operasi yang tumpang tindih selesai. Status penyelesaian akhir dapat diambil ketika metode penyelesaian yang sesuai disinyalkan ketika operasi telah selesai.
lpvOverlapped
Penunjuk ke struktur WSAOVERLAPPED .
Jika soket dibuat tanpa atribut yang tumpang tindih, parameter lpOverlapped diabaikan.
Jika s dibuka dengan atribut yang tumpang tindih dan parameter lpOverlapped bukan NULL, operasi dilakukan sebagai operasi yang tumpang tindih (asinkron). Dalam hal ini, parameter lpOverlapped harus menunjuk ke struktur WSAOVERLAPPED yang valid.
Untuk operasi yang tumpang tindih, fungsi WSAIoctl atau WSPIoctl segera kembali, dan metode penyelesaian yang sesuai disinyalkan ketika operasi telah selesai. Jika tidak, fungsi tidak kembali sampai operasi selesai atau terjadi kesalahan.
lpCompletionRoutine
Jenis: LPWSAOVERLAPPED_COMPLETION_ROUTINE _In_opt_
Penunjuk ke rutinitas penyelesaian yang dipanggil ketika operasi telah selesai (diabaikan untuk soket yang tidak tumpang tindih).
lpThreadId
Penunjuk ke struktur WSATHREADID yang akan digunakan oleh penyedia dalam panggilan berikutnya ke WPUQueueApc. Penyedia harus menyimpan struktur WSATHREADID yang direferensikan (bukan penunjuk ke yang sama) sampai setelah fungsi WPUQueueApc kembali.
Catatan Parameter ini hanya berlaku untuk fungsi WSPIoctl .
lpErrno
Penunjuk ke kode kesalahan.
Catatan Parameter ini hanya berlaku untuk fungsi WSPIoctl .
Nilai kembali
Jika operasi berhasil diselesaikan, fungsi WSAIoctl atau WSPIoctl mengembalikan nol.
Jika operasi gagal atau tertunda, fungsi WSAIoctl atau WSPIoctl mengembalikan SOCKET_ERROR. Untuk mendapatkan informasi kesalahan yang diperluas, hubungi WSAGetLastError.
Kode kesalahan | Makna |
---|---|
WSA_IO_PENDING | Operasi I/O yang tumpang tindih sedang berlangsung. Nilai ini dikembalikan jika operasi yang tumpang tindih berhasil dimulai dan penyelesaian akan ditunjukkan di lain waktu. |
WSA_OPERATION_ABORTED | Operasi I/O telah dibatalkan karena keluarnya utas atau permintaan aplikasi. Kesalahan ini dikembalikan jika operasi yang tumpang tindih dibatalkan karena penutupan soket atau eksekusi perintah SIO_FLUSH IOCTL. |
WSAEFAULT | Sistem mendeteksi alamat penunjuk yang tidak valid dalam mencoba menggunakan argumen pointer dalam panggilan. Kesalahan ini dikembalikan dari parameter lpOverlapped atau lpCompletionRoutine tidak sepenuhnya terkandung dalam bagian ruang alamat pengguna yang valid. |
WSAEINPROGRESS | Operasi pemblokiran saat ini sedang dijalankan. Kesalahan ini dikembalikan jika fungsi dipanggil saat panggilan balik sedang berlangsung. |
WSAEINTR | Operasi pemblokiran terganggu oleh panggilan ke WSACancelBlockingCall. Kesalahan ini dikembalikan jika operasi pemblokiran terganggu. |
WSAEINVAL | Argumen yang tidak valid disediakan. Kesalahan ini dikembalikan jika parameter dwIoControlCode bukan perintah yang valid, atau parameter input yang ditentukan tidak dapat diterima, atau perintah tidak berlaku untuk jenis soket yang ditentukan. |
WSAENETDOWN | Operasi soket menemukan jaringan mati. Kesalahan ini dikembalikan jika subsistem jaringan gagal. |
WSAENOTSOCK | Operasi dicoba pada sesuatu yang bukan soket. Kesalahan ini dikembalikan jika deskriptor s bukan soket. |
WSAEOPNOTSUPP | Operasi yang dicoba tidak didukung untuk jenis objek yang direferensikan. Kesalahan ini dikembalikan jika perintah IOCTL yang ditentukan tidak didukung. Kesalahan ini juga dikembalikan jika SIO_RELEASE_PORT_RESERVATION IOCTL tidak didukung oleh penyedia transportasi. Kesalahan ini juga dikembalikan ketika upaya untuk menggunakan SIO_RELEASE_PORT_RESERVATION IOCTL dibuat pada soket selain UDP atau TCP. |
Keterangan
IOCTL SIO_RELEASE_PORT_RESERVATION didukung pada Windows Vista dan versi sistem operasi yang lebih baru.
Aplikasi dan layanan yang perlu memesan port termasuk dalam dua kategori. Kategori pertama mencakup komponen yang membutuhkan port tertentu sebagai bagian dari operasi mereka. Komponen tersebut umumnya akan lebih memilih untuk menentukan port yang diperlukan pada waktu penginstalan (misalnya dalam manifes aplikasi). Kategori kedua mencakup komponen yang memerlukan port atau blok port yang tersedia saat runtime. Kedua kategori ini sesuai dengan permintaan reservasi port tertentu dan kartubebas. Permintaan reservasi tertentu mungkin persisten atau runtime, sementara permintaan reservasi port wildcard hanya didukung saat runtime.
IOCTL SIO_ACQUIRE_PORT_RESERVATION digunakan untuk meminta reservasi runtime untuk blok port TCP atau UDP. Untuk reservasi port runtime, kumpulan port mengharuskan reservasi dikonsumsi dari proses yang soket reservasinya diberikan. Reservasi port runtime hanya berlangsung selama masa pakai soket tempat IOCTL SIO_ACQUIRE_PORT_RESERVATION dipanggil. Sebaliknya, reservasi port persisten yang dibuat menggunakan fungsi CreatePersistentTcpPortReservation atau CreatePersistentUdpPortReservation dapat dikonsumsi oleh proses apa pun dengan kemampuan untuk mendapatkan reservasi persisten.
IOCTL SIO_RELEASE_PORT_RESERVATION digunakan untuk merilis reservasi runtime untuk blok port TCP atau UDP.
Jika parameter lpOverlapped dan lpCompletionRoutine adalah NULL, soket dalam fungsi ini akan diperlakukan sebagai soket yang tidak tumpang tindih. Untuk parameter soket yang tidak tumpang tindih, lpOverlapped dan lpCompletionRoutine diabaikan, kecuali bahwa fungsi dapat memblokir jika soket dalam mode pemblokiran. Jika soket dalam mode non-pemblokiran, fungsi ini akan tetap memblokir karena IOCTL khusus ini tidak mendukung mode non-pemblokiran.
Untuk soket yang tumpang tindih, operasi yang tidak dapat segera diselesaikan akan dimulai, dan penyelesaian akan ditunjukkan di lain waktu.
IOCTL apa pun dapat memblokir tanpa batas waktu, tergantung pada implementasi penyedia layanan. Jika aplikasi tidak dapat mentolerir pemblokiran dalam panggilan fungsi WSAIoctl atau WSPIoctl , I/O yang tumpang tindih akan disarankan untuk IOCTL yang kemungkinan besar akan diblokir.
IOCTL SIO_RELEASE_PORT_RESERVATION dapat gagal dengan WSAEINTR atau WSA_OPERATION_ABORTED dalam kasus berikut:
- Permintaan dibatalkan oleh Manajer I/O.
- Soket ditutup.
Contoh
Contoh berikut memperoleh reservasi port runtime lalu merilis reservasi port runtime.
#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;
}
Lihat juga
CreatePersistentTcpPortReservation
CreatePersistentUdpPortReservation
DeletePersistentTcpPortReservation
DeletePersistentUdpPortReservation
LookupPersistentTcpPortReservation
LookupPersistentUdpPortReservation