Fungsi CreatePersistentTcpPortReservation (iphlpapi.h)

Fungsi CreatePersistentTcpPortReservation membuat reservasi port TCP persisten untuk blok berturut-turut port TCP di komputer lokal.

Sintaks

IPHLPAPI_DLL_LINKAGE ULONG CreatePersistentTcpPortReservation(
  [in]  USHORT   StartPort,
  [in]  USHORT   NumberOfPorts,
  [out] PULONG64 Token
);

Parameter

[in] StartPort

Nomor port TCP awal dalam urutan byte jaringan.

[in] NumberOfPorts

Jumlah nomor port TCP yang akan dicadangkan.

[out] Token

Pointer ke token reservasi port yang dikembalikan jika fungsi berhasil.

Nilai kembali

Jika fungsi berhasil, nilai yang dikembalikan adalah NO_ERROR.

Jika fungsi gagal, nilai yang dikembalikan adalah salah satu kode kesalahan berikut.

Menampilkan kode Deskripsi
ERROR_ACCESS_DENIED
Akses ditolak. Kesalahan ini dikembalikan dalam beberapa kondisi yang mencakup hal berikut: pengguna tidak memiliki hak istimewa administratif yang diperlukan di komputer lokal atau aplikasi tidak berjalan dalam shell yang ditingkatkan sebagai Administrator bawaan (administrator RunAs).
ERROR_INVALID_PARAMETER
Parameter yang tidak valid diteruskan ke fungsi.

Kesalahan ini dikembalikan jika nol diteruskan dalam parameter StartPort atau NumberOfPorts . Kesalahan ini juga dikembalikan jika parameter NumberOfPorts terlalu besar blok port tergantung pada parameter StartPort bahwa blok port yang dapat dialokasikan akan melebihi port maksimum yang dapat dialokasikan.

ERROR_SHARING_VIOLATION
Proses tidak bisa mengakses file karena sedang digunakan oleh proses lain. Kesalahan ini dikembalikan jika port TCP di blok port TCP yang ditentukan oleh parameter StartPort dan NumberOfPorts sudah digunakan. Kesalahan ini juga dikembalikan jika reservasi persisten untuk blok port TCP yang ditentukan oleh parameter StartPort dan NumberOfPorts cocok atau tumpang tindih dengan reservasi persisten untuk blok port TCP yang sudah dibuat.
Lainnya
Gunakan FormatMessage untuk mendapatkan string pesan untuk kesalahan yang dikembalikan.

Keterangan

Fungsi CreatePersistentTcpPortReservation didefinisikan pada Windows Vista dan yang lebih baru.

Fungsi CreatePersistentTcpPortReservation digunakan untuk menambahkan reservasi persisten untuk blok port TCP.

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.

Fungsi CreatePersistentTcpPortReservation menyediakan kemampuan bagi aplikasi atau layanan untuk memesan blok port TCP yang persisten. Reservasi port TCP persisten dicatat di penyimpanan persisten untuk modul TCP di Windows.

Penelepon mendapatkan reservasi port persisten dengan menentukan berapa banyak port yang diperlukan dan apakah rentang tertentu diperlukan. Jika permintaan dapat dipenuhi, fungsi CreatePersistentTcpPortReservation mengembalikan token ULONG64 buram unik, yang kemudian mengidentifikasi reservasi. Reservasi port TCP persisten dapat dirilis dengan memanggil fungsi DeletePersistentTcpPortReservation . Perhatikan bahwa token untuk reservasi port TCP persisten tertentu dapat berubah setiap kali sistem dimulai ulang.

Windows tidak menerapkan keamanan antar komponen untuk reservasi persisten yang diperoleh menggunakan fungsi-fungsi ini. Ini berarti bahwa jika komponen diberikan kemampuan untuk mendapatkan reservasi port persisten, komponen tersebut secara otomatis mendapatkan kemampuan untuk mengonsumsi reservasi port persisten yang diberikan kepada komponen lain pada sistem. Keamanan tingkat proses diberlakukan untuk reservasi runtime, tetapi kontrol tersebut tidak dapat diperluas ke reservasi port persisten yang dibuat menggunakan fungsi CreatePersistentTcpPortReservation atau CreatePersistentUdpPortReservation .

Setelah reservasi port TCP persisten diperoleh, aplikasi dapat meminta penetapan port dari reservasi port TCP dengan membuka soket TCP, lalu memanggil fungsi WSAIoctl yang menentukan SIO_ASSOCIATE_PORT_RESERVATION IOCTL dan meneruskan token reservasi sebelum mengeluarkan panggilan ke fungsi ikat pada soket.

IOCTL SIO_ACQUIRE_PORT_RESERVATION dapat 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 dapat digunakan oleh proses apa pun dengan kemampuan untuk mendapatkan reservasi persisten.

Fungsi CreatePersistentTcpPortReservation hanya dapat dipanggil oleh pengguna yang masuk sebagai anggota grup Administrator. Jika CreatePersistentTcpPortReservation dipanggil oleh pengguna yang bukan anggota grup Administrator, panggilan fungsi akan gagal dan ERROR_ACCESS_DENIED dikembalikan. Fungsi ini juga dapat gagal karena kontrol akun pengguna (UAC) pada Windows Vista dan yang lebih baru. Jika aplikasi yang berisi fungsi ini dijalankan oleh pengguna yang masuk sebagai anggota grup Administrator selain Administrator bawaan, panggilan ini akan gagal kecuali aplikasi telah ditandai dalam file manifes dengan requestedExecutionLevel yang diatur ke requireAdministrator. Jika aplikasi tidak memiliki file manifes ini, pengguna yang masuk sebagai anggota grup Administrator selain Administrator bawaan kemudian harus menjalankan aplikasi dalam shell yang ditingkatkan sebagai Administrator bawaan (administrator RunAs) agar fungsi ini berhasil.

Contoh

Contoh berikut membuat reservasi port TCP persisten, lalu membuat soket dan mengalokasikan port dari reservasi port, lalu menutup soket dan menghapus reservasi port TCP.

Contoh ini harus dijalankan oleh pengguna yang merupakan anggota grup Administrator. Cara paling sederhana untuk menjalankan contoh ini adalah dalam shell yang ditingkatkan sebagai Administrator bawaan (administrator 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;
}

Persyaratan

Persyaratan Nilai
Klien minimum yang didukung Windows Vista [hanya aplikasi desktop]
Server minimum yang didukung Windows Server 2008 [hanya aplikasi desktop]
Target Platform Windows
Header iphlpapi.h
Pustaka Iphlpapi.lib
DLL Iphlpapi.dll

Lihat juga

CreatePersistentUdpPortReservation

DeletePersistentTcpPortReservation

DeletePersistentUdpPortReservation

LookupPersistentTcpPortReservation

LookupPersistentUdpPortReservation

SIO_ACQUIRE_PORT_RESERVATION

SIO_ASSOCIATE_PORT_RESERVATION

SIO_RELEASE_PORT_RESERVATION

WSAIoctl

Mengikat