Funzione GetAddrInfoExW (ws2tcpip.h)
La funzione GetAddrInfoEx fornisce la risoluzione dei nomi indipendente dal protocollo con parametri aggiuntivi per qualificare i provider di spazi dei nomi che devono gestire la richiesta.
Sintassi
INT WSAAPI GetAddrInfoExW(
[in, optional] PCWSTR pName,
[in, optional] PCWSTR pServiceName,
[in] DWORD dwNameSpace,
[in, optional] LPGUID lpNspId,
[in, optional] const ADDRINFOEXW *hints,
[out] PADDRINFOEXW *ppResult,
[in, optional] timeval *timeout,
[in, optional] LPOVERLAPPED lpOverlapped,
[in, optional] LPLOOKUPSERVICE_COMPLETION_ROUTINE lpCompletionRoutine,
[out, optional] LPHANDLE lpHandle
);
Parametri
[in, optional] pName
Puntatore a una stringa con terminazione NULL contenente un nome host (nodo) o una stringa di indirizzo host numerico. Per il protocollo Internet, la stringa di indirizzo host numerico è un indirizzo IPv4 punteggiato-decimale o un indirizzo esadecimale IPv6.
[in, optional] pServiceName
Puntatore a una stringa facoltativa con terminazione NULL contenente un nome di servizio o un numero di porta rappresentato come stringa.
Un nome del servizio è un alias stringa per un numero di porta. Ad esempio, "http" è un alias per la porta 80 definita da Internet Engineering Task Force (IETF) come porta predefinita usata dai server Web per il protocollo HTTP. I valori possibili per il parametro pServiceName quando non viene specificato un numero di porta sono elencati nel file seguente:
%WINDIR%\system32\drivers\etc\services
[in] dwNameSpace
Identificatore dello spazio dei nomi facoltativo che determina quali provider di spazi dei nomi vengono sottoposti a query. Il passaggio di un identificatore dello spazio dei nomi specifico comporterà solo i provider dello spazio dei nomi che supportano la query dello spazio dei nomi specificato. Se si specifica NS_ALL verrà eseguita una query in tutti i provider di spazi dei nomi installati e attivi.
Le opzioni per il parametro dwNameSpace sono elencate nel file di inclusione Winsock2.h . Diversi provider di spazi dei nomi vengono aggiunti in Windows Vista e versioni successive. È possibile installare altri provider di spazi dei nomi, pertanto i valori possibili seguenti sono solo quelli comunemente disponibili. Sono possibili molti altri valori.
[in, optional] lpNspId
Puntatore a un GUID facoltativo di un provider di spazi dei nomi specifico per eseguire una query nel caso in cui più provider di spazi dei nomi siano registrati in un singolo spazio dei nomi, ad esempio NS_DNS. Se si passa il GUID per un provider di spazi dei nomi specifico, verrà eseguita una query solo sul provider di spazi dei nomi specificato. È possibile chiamare la funzione WSAEnumNameSpaceProviders per recuperare il GUID per un provider di spazi dei nomi.
[in, optional] hints
Puntatore a una struttura addrinfoex che fornisce suggerimenti sul tipo di socket supportato dal chiamante.
I membri ai_addrlen, ai_canonname, ai_addr e ai_next della struttura addrinfoex a cui punta il parametro pHints devono essere zero o NULL. In caso contrario, la funzione GetAddrInfoEx avrà esito negativo con WSANO_RECOVERY.
Per altri dettagli, vedere la sezione Osservazioni.
[out] ppResult
Puntatore a un elenco collegato di una o più strutture addrinfoex che contengono informazioni di risposta sull'host.
[in, optional] timeout
Parametro facoltativo che indica il tempo, espresso in millisecondi, per attendere una risposta dal provider dello spazio dei nomi prima di interrompere la chiamata.
Questo parametro è supportato solo quando la macro UNICODE o _UNICODE è stata definita nelle origini prima di chiamare la funzione GetAddrInfoEx . In caso contrario, questo parametro è attualmente riservato e deve essere impostato su NULL perché un'opzione di timeout non è supportata.
[in, optional] lpOverlapped
Puntatore facoltativo a una struttura sovrapposta utilizzata per l'operazione asincrona.
Questo parametro è supportato solo quando la macro UNICODE o _UNICODE è stata definita nelle origini prima di chiamare la funzione GetAddrInfoEx .
In Windows 8 e Windows Server 2012, se non viene specificato alcun parametro lpCompletionRoutine , il membro hEvent della struttura OVERLAPPED deve essere impostato su un evento di reimpostazione manuale da chiamare al completamento di una chiamata asincrona. Se è stata specificata una routine di completamento, il membro hEvent deve essere NULL. Quando è stato impostato l'evento specificato da hEvent , è possibile recuperare il risultato dell'operazione chiamando la funzione GetAddrInfoExOverlappedResult .
In Windows 8 e Windows Server 2012 ogni volta che la macro UNICODE o _UNICODE non è definita, questo parametro è attualmente riservato e deve essere impostato su NULL.
In Windows 7 e Windows Server 2008 R2 o versioni precedenti, questo parametro è attualmente riservato e deve essere impostato su NULL perché le operazioni asincrone non sono supportate.
[in, optional] lpCompletionRoutine
Puntatore facoltativo a una funzione da richiamare al completamento corretto per le operazioni asincrone.
Questo parametro è supportato solo quando la macro UNICODE o _UNICODE è stata definita nelle origini prima di chiamare la funzione GetAddrInfoEx .
Se questo parametro viene specificato, deve essere un puntatore a una funzione con la firma seguente:
typedef
void
(CALLBACK * LPLOOKUPSERVICE_COMPLETION_ROUTINE)(
__in DWORD dwError,
__in DWORD dwBytes,
__in LPWSAOVERLAPPED lpOverlapped
);
Al termine dell'operazione asincrona, la routine di completamento verrà richiamata con il parametro lpOverlapped impostato sul valore del parametro lpOverlapped passato a GetAddrInfoEx. Il membro Pointer della struttura OVERLAPPED verrà impostato sul valore del parametro ppResult della chiamata originale. Se il membro Puntatore punta a un puntatore non NULL alla struttura addrinfoex , è responsabilità del chiamante chiamare FreeAddrInfoEx per liberare la struttura addrinfoex . Il parametro dwError passato alla routine di completamento verrà impostato su un codice di errore Winsock. Il parametro dwBytes è riservato per uso futuro e deve essere ignorato.
In Windows 8 e Windows Server 2012 ogni volta che la macro UNICODE o _UNICODE non è definita, questo parametro è attualmente riservato e deve essere impostato su NULL.
In Windows 7 e Windows Server 2008 R2 o versioni precedenti, questo parametro è attualmente riservato e deve essere impostato su NULL perché le operazioni asincrone non sono supportate.
[out, optional] lpHandle
Puntatore facoltativo usato solo per le operazioni asincrone.
Questo parametro è supportato solo quando la macro UNICODE o _UNICODE è stata definita nelle origini prima di chiamare la funzione GetAddrInfoEx .
In Windows 8 e Windows Server 2012, se la funzione GetAddrInfoEx verrà completata in modo asincrono, il puntatore restituito in questo campo può essere usato con la funzione GetAddrInfoExCancel . L'handle restituito è valido quando GetAddrInfoEx viene restituito finché non viene chiamata la routine di completamento, l'evento viene attivato o la funzione GetAddrInfoExCancel viene chiamata con questo handle.
In Windows 8 e Windows Server 2012 ogni volta che la macro UNICODE o _UNICODE non è definita, questo parametro è attualmente riservato e deve essere impostato su NULL.
In Windows 7 e Windows Server 2008 R2 o versioni precedenti, questo parametro è attualmente riservato e deve essere impostato su NULL perché le operazioni asincrone non sono supportate.
Valore restituito
In caso di esito positivo, GetAddrInfoEx restituisce NO_ERROR (0). L'errore restituisce un codice di errore Windows Sockets diverso da zero, come indicato nei codici di errore di Windows Sockets.
La maggior parte dei codici di errore diversi da zero restituiti dalla funzione GetAddrInfoEx viene mappato al set di errori descritti dalle raccomandazioni di Internet Engineering Task Force (IETF). La tabella seguente illustra questi codici di errore e i relativi equivalenti WSA. È consigliabile usare i codici di errore WSA, in quanto offrono informazioni sugli errori familiari e complete per i programmatori Winsock.
Valore di errore | Equivalente WSA | Descrizione |
---|---|---|
EAI_AGAIN | WSATRY_AGAIN | Si è verificato un errore temporaneo nella risoluzione dei nomi. |
EAI_BADFLAGS | WSAEINVAL | È stato fornito un parametro non valido. Questo errore viene restituito se uno dei parametri riservati non è NULL. Questo errore viene restituito anche se è stato specificato un valore non valido per il membro ai_flags del parametro pHints . |
EAI_FAIL | WSANO_RECOVERY | Si è verificato un errore non recuperabile nella risoluzione dei nomi. |
EAI_FAMILY | WSAEAFNOSUPPORT | Il ai_family membro del parametro pHints non è supportato. |
EAI_MEMORY | WSA_NOT_ENOUGH_MEMORY | Si è verificato un errore di allocazione della memoria. |
EAI_NONAME | WSAHOST_NOT_FOUND | Il nome non viene risolto per i parametri specificati o i parametri pName e pServiceName non sono stati specificati. |
EAI_SERVICE | WSATYPE_NOT_FOUND | Il parametro pServiceName non è supportato per il membro ai_socktype specificato del parametro pHints . |
EAI_SOCKTYPE | WSAESOCKTNOSUPPORT | Il ai_socktype membro del parametro pHints non è supportato. |
Usare la funzione gai_strerror per stampare messaggi di errore in base ai codici EAI restituiti dalla funzione GetAddrInfoEx . La funzione gai_strerror viene fornita per la conformità ai consigli di IETF, ma non è thread safe. Pertanto, è consigliabile usare le funzioni tradizionali di Windows Sockets, ad esempio WSAGetLastError .
Codice di errore | Significato |
---|---|
Memoria insufficiente per eseguire l'operazione. | |
È stato usato un indirizzo incompatibile con il protocollo richiesto. Questo errore viene restituito se il membro ai_family della struttura addrinfoex a cui punta il parametro pHints non è supportato. | |
Argomento fornito non valido. Questo errore viene restituito se è stato specificato un valore non valido per il membro ai_flags della struttura addrinfoex a cui fa riferimento il parametro pHints . Questo errore viene restituito anche quando il parametro dwNameSpace è NS_PNRPNAME o NS_PNRPCLOUD e il servizio nome peer-to-peer non è operativo. | |
Il supporto per il tipo di socket specificato non esiste in questa famiglia di indirizzi. Questo errore viene restituito se il membro ai_socktype della struttura addrinfoex a cui punta il parametro pHints non è supportato. | |
L'host è sconosciuto. Questo errore viene restituito se il nome non viene risolto per i parametri specificati o i parametri pName e pServiceName non sono stati specificati. | |
Il nome richiesto è valido, ma non sono stati trovati dati del tipo richiesto. | |
Si è verificato un errore irreversibile durante una ricerca nel database. Questo errore viene restituito se si è verificato un errore non recuperabile nella risoluzione dei nomi. | |
Prima di usare questa funzione, è necessario eseguire una chiamata WSAStartup riuscita. | |
Nessun servizio di questo tipo è noto. Impossibile trovare il servizio nello spazio dei nomi specificato. Questo errore viene restituito se il parametro pName o pServiceName non viene trovato per lo spazio dei nomi specificato nel parametro dwNameSpace o lo spazio dei nomi specificato nel parametro dwNameSpace non è installato. | |
Generalmente, questo è un errore temporaneo che si verifica durante la risoluzione dei nomi host e significa che il server locale non ha ricevuto una risposta da un server autorevole. Questo errore viene restituito quando si è verificato un errore temporaneo nella risoluzione dei nomi. | |
La classe specificata non è stata trovata. Il parametro pServiceName non è supportato per il membro ai_socktype specificato della struttura addrinfoex a cui fa riferimento il parametro pHints . |
Commenti
La funzione GetAddrInfoEx fornisce la traduzione indipendente dal protocollo dal nome host all'indirizzo e dal nome del servizio al numero di porta. La funzione GetAddrInfoEx è una versione avanzata delle funzioni getaddrinfo e GetAddrInfoW . La funzione GetAddrInfoEx consente di specificare il provider di spazi dei nomi per risolvere la query.
La funzione GetAddrInfoEx aggrega e restituisce i risultati da più provider di spazi dei nomi, a meno che non sia specificato un provider di spazi dei nomi specifico. Per l'uso con il protocollo IPv6 e IPv4, la risoluzione dei nomi può essere dal dns (Domain Name System), da un file host locale, da un provider di posta elettronica (lo spazio dei nomi NS_EMAIL ) o da altri meccanismi di denominazione.
Quando viene definito UNICODE o _UNICODE, GetAddrInfoEx viene definito in GetAddrInfoExW, la versione Unicode di questa funzione. I parametri stringa vengono definiti per il tipo di dati PWSTR e viene usata la struttura ADDRINFOEXW . In Windows 8 e Windows Server 2012, il timeout, lpOverlapped, lpCompletionRoutine e i parametri lpHandle possono essere usati per chiamare la funzione GetAddrInfoEx in modo che possa completare in modo asincrono.
Quando UNICODE o _UNICODE non è definito, GetAddrInfoEx viene definito in GetAddrInfoExA, la versione ANSI di questa funzione. I parametri stringa sono del tipo di dati PCSTR e viene usata la struttura ADDRINFOEXA . Il timeout, lpOverlapped, lpCompletionRoutine e i parametri lpHandle devono essere impostati su NULL.
Uno o entrambi i parametri pName o pServiceName devono puntare a una stringa con terminazione NULL. In genere vengono forniti entrambi.
Al termine dell'operazione, viene restituito un elenco collegato di strutture addrinfoex nel parametro ppResult . L'elenco può essere elaborato seguendo il puntatore fornito nel membro ai_next di ogni struttura addrinfoex restituita finché non viene rilevato un puntatore NULL . In ogni struttura addrinfoex restituita, i ai_family, i ai_socktype e i membri ai_protocol corrispondono ai rispettivi argomenti in una chiamata di funzione socket o WSASocket . Inoltre, il membro ai_addr in ogni struttura addrinfoex restituita punta a una struttura di indirizzi socket compilata, la lunghezza di cui è specificato nel relativo membro ai_addrlen .
Se il parametro pName punta a un nome computer, vengono restituiti tutti gli indirizzi permanenti per il computer che può essere usato come indirizzo di origine. In Windows Vista e versioni successive, questi indirizzi includono tutti gli indirizzi IP unicast restituiti dalla funzione GetUnicastIpAddressTable o GetUnicastIpAddressEntry in cui il membro SkipAsSource è impostato su false nella struttura MIB_UNICASTIPADDRESS_ROW.
Se il parametro pName punta a una stringa uguale a "localhost", vengono restituiti tutti gli indirizzi di loopback nel computer locale.
Se il parametro pName contiene una stringa vuota, vengono restituiti tutti gli indirizzi registrati nel computer locale.
In Windows Server 2003 e versioni successive se il parametro pName punta a una stringa uguale a ".. localmachine", tutti gli indirizzi registrati nel computer locale vengono restituiti.
Se il parametro pName fa riferimento a un nome del server virtuale del cluster, vengono restituiti solo gli indirizzi del server virtuale. In Windows Vista e versioni successive, questi indirizzi includono tutti gli indirizzi IP unicast restituiti dalla struttura GetUnicastIpAddressTable o GetUnicastIpAddressEntry in cui il membro SkipAsSource è impostato su true nella struttura MIB_UNICASTIPADDRESS_ROW. Per altre informazioni sul clustering, vedere Clustering di Windows .
Windows 7 con Service Pack 1 (SP1) e Windows Server 2008 R2 con Service Pack 1 (SP1) aggiungono supporto Netsh.exe per l'impostazione dell'attributo SkipAsSource in un indirizzo IP. Questo modifica anche il comportamento in modo che se il membro SkipAsSource nella struttura di MIB_UNICASTIPADDRESS_ROW è impostato su false, l'indirizzo IP verrà registrato in DNS. Se il membro SkipAsSource è impostato su true, l'indirizzo IP non è registrato in DNS.
Un hotfix è disponibile per Windows 7 e Windows Server 2008 R2 che aggiunge il supporto a Netsh.exe per impostare l'attributo SkipAsSource su un indirizzo IP. Questo hotfix modifica anche il comportamento in modo che se il membro SkipAsSource nella struttura MIB_UNICASTIPADDRESS_ROW è impostato su false, l'indirizzo IP verrà registrato in DNS. Se il membro SkipAsSource è impostato su true, l'indirizzo IP non è registrato in DNS. Per altre informazioni, vedere Knowledge Base (KB) 2386184.
Un hotfix simile è disponibile anche per Windows Vista con Service Pack 2 (SP2) e Windows Server 2008 con Service Pack 2 (SP2) che aggiunge il supporto a Netsh.exe per impostare l'attributo SkipAsSource in un indirizzo IP. Questo hotfix modifica anche il comportamento in modo che se il membro SkipAsSource nella struttura MIB_UNICASTIPADDRESS_ROW è impostato su false, l'indirizzo IP verrà registrato in DNS. Se il membro SkipAsSource è impostato su true, l'indirizzo IP non è registrato in DNS.
I chiamanti della funzione GetAddrInfoEx possono fornire hint sul tipo di socket supportato tramite una struttura addrinfoex a cui punta il parametro pHints . Quando viene usato il parametro pHints , le regole seguenti si applicano alla struttura addrinfoex associata:
- Un valore di AF_UNSPEC per ai_family indica che il chiamante accetterà solo le famiglie di indirizzi AF_INET e AF_INET6 . Si noti che AF_UNSPEC e PF_UNSPEC sono uguali.
- Un valore pari a zero per ai_socktype indica che il chiamante accetterà qualsiasi tipo di socket.
- Un valore pari a zero per ai_protocol indica che il chiamante accetterà qualsiasi protocollo.
- Il membro ai_addrlen deve essere impostato su zero.
- Il membro ai_canonname deve essere impostato su NULL.
- Il membro ai_addr deve essere impostato su NULL.
- Il membro ai_next deve essere impostato su NULL.
Altri valori nella struttura addrinfoex forniti nel parametro pHints indicano requisiti specifici. Ad esempio, se il chiamante gestisce solo IPv4 e non gestisce IPv6, il membro ai_family deve essere impostato su AF_INET. Per un altro esempio, se il chiamante gestisce solo TCP e non gestisce UDP, il membro ai_socktype deve essere impostato su SOCK_STREAM.
Se il parametro pHints è un puntatore NULL , la funzione GetAddrInfoEx la considera come se la struttura addrinfoex in pHints fosse inizializzata con il relativo membro ai_family impostato su AF_UNSPEC e tutti gli altri membri impostati su NULL o zero.
Quando GetAddrInfoEx viene chiamato da un servizio, se l'operazione è il risultato di un processo utente che chiama il servizio, il servizio deve rappresentare l'utente. Ciò consente di applicare correttamente la sicurezza.
La funzione GetAddrInfoEx può essere usata per convertire una rappresentazione stringa di testo di un indirizzo IP in una struttura addrinfoex contenente una struttura sockaddr per l'indirizzo IP e altre informazioni. Per essere usato in questo modo, la stringa puntata dal parametro pName deve contenere una rappresentazione di testo di un indirizzo IP e la struttura addrinfoex a cui punta il parametro pHints deve avere il flag AI_NUMERICHOST impostato nel membro ai_flags . La stringa a cui punta il parametro pName può contenere una rappresentazione di testo di un indirizzo IPv4 o di un indirizzo IPv6. L'indirizzo IP di testo viene convertito in una struttura addrinfoex a cui punta il parametro ppResult . La struttura addrinfoex restituita contiene una struttura sockaddr per l'indirizzo IP insieme ad altre informazioni sull'indirizzo IP.
È possibile installare più provider di spazi dei nomi in un computer locale per lo stesso spazio dei nomi. Ad esempio, il software di rete TCP/IP di base viene registrato per lo spazio dei nomi NS_DNS. Microsoft Forefront Threat Management Gateway (TMG) e il server Microsoft Internet Security and Acceleration (ISA) meno recente includono software client firewall che registra anche per lo spazio dei nomi NS_DNS. Quando il parametro dwNameSpace è impostato su un valore (NS_DNS, ad esempio) e il parametro lpNspId è NULL, i risultati restituiti dalla funzione GetAddrInfoEx sono i risultati uniti da tutti i provider di spazi dei nomi registrati per lo spazio dei nomi specificato con risultati duplicati eliminati. Il parametro lpNspId deve essere impostato sul GUID del provider di spazi dei nomi specifico se deve essere eseguito una query solo su un singolo provider di spazi dei nomi.
Se il parametro pNameSpace è impostato su NS_ALL, i risultati della query su tutti i provider di spazi dei nomi vengono uniti e restituiti. In questo caso, le risposte duplicate possono essere restituite nei risultati a cui fa riferimento il parametro ppResult se più provider di spazi dei nomi restituiscono le stesse informazioni.
In Windows 8 e Windows Server 2012, se la funzione GetAddrInfoEx verrà completata in modo asincrono, il puntatore restituito nel parametro lpHandle può essere usato con la funzione GetAddrInfoExCancel . L'handle restituito è valido quando GetAddrInfoEx restituisce finché non viene chiamata la routine di completamento, l'evento viene attivato o la funzione GetAddrInfoExCancel viene chiamata con questo handle.
Liberare le informazioni sugli indirizzi dall'allocazione dinamica
Tutte le informazioni restituite dalla funzione GetAddrInfoEx a cui punta il parametro ppResult vengono allocate in modo dinamico, incluse tutte le strutture addrinfoex , le strutture di indirizzi socket e le stringhe dei nomi host canoniche a cui puntano le strutture addrinfoex . La memoria allocata da una chiamata riuscita a questa funzione deve essere rilasciata con una chiamata successiva a FreeAddrInfoEx.Codice di esempio
Nell'esempio seguente viene illustrato l'uso della funzione GetAddrInfoEx .#ifndef UNICODE
#define UNICODE
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <objbase.h>
#include <stdio.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
// Need to link with Ole32.lib to print GUID
#pragma comment(lib, "ole32.lib")
int __cdecl wmain(int argc, wchar_t ** argv)
{
//-----------------------------------------
// Declare and initialize variables
WSADATA wsaData;
int iResult;
DWORD dwRetval;
int i = 1;
DWORD dwNamespace = NS_ALL;
LPGUID lpNspid = NULL;
ADDRINFOEX *result = NULL;
ADDRINFOEX *ptr = NULL;
ADDRINFOEX hints;
// LPSOCKADDR sockaddr_ip;
struct sockaddr_in *sockaddr_ipv4;
struct sockaddr_in6 *sockaddr_ipv6;
// DWORD ipbufferlength = 46;
wchar_t ipstringbuffer[46];
// variables needed to print namespace provider GUID
int iRet = 0;
WCHAR GuidString[40] = { 0 };
// Validate the parameters
if (argc != 4) {
wprintf(L"usage: %ws <hostname> <servicename> <namespace>\n", argv[0]);
wprintf(L"getaddrinfoex provides protocol-independent translation\n");
wprintf(L" from a host name to an IP address\n");
wprintf(L"%ws example usage\n", argv[0]);
wprintf(L" %ws www.contoso.com 0 12\n", argv[0]);
wprintf(L" looks up the www.contoso.com in the NS_DNS namespace\n",
argv[0]);
return 1;
}
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
wprintf(L"WSAStartup failed: %d\n", iResult);
return 1;
}
//--------------------------------
// Setup the hints address info structure
// which is passed to the getaddrinfo() function
ZeroMemory(&hints, sizeof (hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
dwNamespace = (DWORD) _wtoi(argv[3]);
wprintf(L"Calling GetAddrInfoEx with following parameters:\n");
wprintf(L"\tName = %ws\n", argv[1]);
wprintf(L"\tServiceName (or port) = %ws\n", argv[2]);
wprintf(L"\tNamespace = %s (", argv[3]);
switch (dwNamespace) {
case NS_ALL:
wprintf(L"(NS_ALL)\n");
break;
case NS_DNS:
wprintf(L"(NS_DNS)\n");
break;
case NS_NETBT:
wprintf(L"NS_NETBT");
break;
case NS_WINS:
wprintf(L"NS_WINS");
break;
case NS_NLA:
wprintf(L"NS_NLA");
break;
case NS_BTH:
wprintf(L"NS_BTH");
break;
case NS_NTDS:
wprintf(L"NS_NTDS");
break;
case NS_EMAIL:
wprintf(L"NS_EMAIL");
break;
case NS_PNRPNAME:
wprintf(L"NS_PNRPNAME");
break;
case NS_PNRPCLOUD:
wprintf(L"NS_PNRPCLOUD");
break;
default:
wprintf(L"Other");
break;
}
wprintf(L")\n\n");
//--------------------------------
// Call getaddrinfoex(). If the call succeeds,
// the result variable will hold a linked list
// of addrinfo structures containing response
// information
dwRetval =
GetAddrInfoEx(argv[1], argv[2], dwNamespace, lpNspid, &hints, &result,
NULL, NULL, NULL, NULL);
if (dwRetval != 0) {
wprintf(L"GetAddrInfoEx failed with error: %d\n", dwRetval);
WSACleanup();
return 1;
}
wprintf(L"GetAddrInfoEx returned success\n");
// Retrieve each address and print out the hex bytes
for (ptr = result; ptr != NULL; ptr = ptr->ai_next) {
wprintf(L"GetAddrInfoEx response %d\n", i++);
wprintf(L"\tFlags: 0x%x\n", ptr->ai_flags);
wprintf(L"\tFamily: ");
switch (ptr->ai_family) {
case AF_UNSPEC:
wprintf(L"Unspecified\n");
break;
case AF_INET:
wprintf(L"AF_INET (IPv4)\n");
// the InetNtop function is available on Windows Vista and later
sockaddr_ipv4 = (struct sockaddr_in *) ptr->ai_addr;
wprintf(L"\tIPv4 address %ws\n",
InetNtop(AF_INET, &sockaddr_ipv4->sin_addr, ipstringbuffer,
46));
// We could also use the WSAAddressToString function
// sockaddr_ip = (LPSOCKADDR) ptr->ai_addr;
// The buffer length is changed by each call to WSAAddresstoString
// So we need to set it for each iteration through the loop for safety
// ipbufferlength = 46;
// iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL,
// ipstringbuffer, &ipbufferlength );
// if (iRetval)
// wprintf(L"WSAAddressToString failed with %u\n", WSAGetLastError() );
// else
// wprintf(L"\tIPv4 address %ws\n", ipstringbuffer);
break;
case AF_INET6:
wprintf(L"AF_INET6 (IPv6)\n");
// the InetNtop function is available on Windows Vista and later
sockaddr_ipv6 = (struct sockaddr_in6 *) ptr->ai_addr;
wprintf(L"\tIPv6 address %ws\n",
InetNtop(AF_INET6, &sockaddr_ipv6->sin6_addr,
ipstringbuffer, 46));
// We could also use WSAAddressToString which also returns the scope ID
// sockaddr_ip = (LPSOCKADDR) ptr->ai_addr;
// The buffer length is changed by each call to WSAAddresstoString
// So we need to set it for each iteration through the loop for safety
// ipbufferlength = 46;
//iRetval = WSAAddressToString(sockaddr_ip, (DWORD) ptr->ai_addrlen, NULL,
// ipstringbuffer, &ipbufferlength );
//if (iRetval)
// wprintf(L"WSAAddressToString failed with %u\n", WSAGetLastError() );
//else
// wprintf(L"\tIPv6 address %ws\n", ipstringbuffer);
break;
default:
wprintf(L"Other %ld\n", ptr->ai_family);
break;
}
wprintf(L"\tSocket type: ");
switch (ptr->ai_socktype) {
case 0:
wprintf(L"Unspecified\n");
break;
case SOCK_STREAM:
wprintf(L"SOCK_STREAM (stream)\n");
break;
case SOCK_DGRAM:
wprintf(L"SOCK_DGRAM (datagram) \n");
break;
case SOCK_RAW:
wprintf(L"SOCK_RAW (raw) \n");
break;
case SOCK_RDM:
wprintf(L"SOCK_RDM (reliable message datagram)\n");
break;
case SOCK_SEQPACKET:
wprintf(L"SOCK_SEQPACKET (pseudo-stream packet)\n");
break;
default:
wprintf(L"Other %ld\n", ptr->ai_socktype);
break;
}
wprintf(L"\tProtocol: ");
switch (ptr->ai_protocol) {
case 0:
wprintf(L"Unspecified\n");
break;
case IPPROTO_TCP:
wprintf(L"IPPROTO_TCP (TCP)\n");
break;
case IPPROTO_UDP:
wprintf(L"IPPROTO_UDP (UDP) \n");
break;
default:
wprintf(L"Other %ld\n", ptr->ai_protocol);
break;
}
wprintf(L"\tLength of this sockaddr: %d\n", ptr->ai_addrlen);
wprintf(L"\tCanonical name: %s\n", ptr->ai_canonname);
if (ptr->ai_blob == NULL)
wprintf(L"\tBlob: (null)\n");
else
wprintf(L"\tLength of the blob: %u\n",
(DWORD) ptr->ai_bloblen);
if (ptr->ai_provider == NULL)
wprintf(L"\tNamespace provider GUID: (null)\n");
else {
iRet =
StringFromGUID2(*(ptr->ai_provider), (LPOLESTR) & GuidString,
39);
// For c rather than C++ source code, the above line needs to be
// iRet = StringFromGUID2(&ptr.ai_provider, (LPOLESTR) &GuidString, 39);
if (iRet == 0)
wprintf(L"StringFromGUID2 failed\n");
else {
wprintf(L"\tNamespace provider: %ws\n", GuidString);
}
}
}
FreeAddrInfoEx(result);
WSACleanup();
return 0;
}
Nell'esempio seguente viene illustrato come usare la funzione GetAddrInfoEx asincrona per risolvere un nome in un indirizzo IP.
//
// This sample demonstrates how to use asynchronous GetAddrInfoEx to
// resolve a name to an IP address.
//
// ResolveName <QueryName>
//
#ifndef UNICODE
#define UNICODE
#endif
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Ws2_32.lib
#pragma comment(lib, "ws2_32.lib")
#define MAX_ADDRESS_STRING_LENGTH 64
//
// Asynchronous query context structure.
//
typedef struct _QueryContext
{
OVERLAPPED QueryOverlapped;
PADDRINFOEX QueryResults;
HANDLE CompleteEvent;
}QUERY_CONTEXT, *PQUERY_CONTEXT;
VOID
WINAPI
QueryCompleteCallback(
_In_ DWORD Error,
_In_ DWORD Bytes,
_In_ LPOVERLAPPED Overlapped
);
int
__cdecl
wmain(
_In_ int Argc, PWCHAR Argv[]
)
{
INT Error = ERROR_SUCCESS;
WSADATA wsaData;
BOOL IsWSAStartupCalled = FALSE;
ADDRINFOEX Hints;
QUERY_CONTEXT QueryContext;
HANDLE CancelHandle = NULL;
DWORD QueryTimeout = 5 * 1000; // 5 seconds
ZeroMemory(&QueryContext, sizeof(QueryContext));
//
// Validate the parameters
//
if (Argc != 2)
{
wprintf(L"Usage: ResolveName <QueryName>\n");
goto exit;
}
//
// All Winsock functions require WSAStartup() to be called first
//
Error = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (Error != 0)
{
wprintf(L"WSAStartup failed with %d\n", Error);
goto exit;
}
IsWSAStartupCalled = TRUE;
ZeroMemory(&Hints, sizeof(Hints));
Hints.ai_family = AF_UNSPEC;
//
// Note that this is a simple sample that waits/cancels a single
// asynchronous query. The reader may extend this to support
// multiple asynchronous queries.
//
QueryContext.CompleteEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (QueryContext.CompleteEvent == NULL)
{
Error = GetLastError();
wprintf(L"Failed to create completion event: Error %d\n", Error);
goto exit;
}
//
// Initiate asynchronous GetAddrInfoExW.
//
// Note GetAddrInfoEx can also be invoked asynchronously using an event
// in the overlapped object (Just set hEvent in the Overlapped object
// and set NULL as completion callback.)
//
// This sample uses the completion callback method.
//
Error = GetAddrInfoExW(Argv[1],
NULL,
NS_DNS,
NULL,
&Hints,
&QueryContext.QueryResults,
NULL,
&QueryContext.QueryOverlapped,
QueryCompleteCallback,
&CancelHandle);
//
// If GetAddrInfoExW() returns WSA_IO_PENDING, GetAddrInfoExW will invoke
// the completion routine. If GetAddrInfoExW returned anything else we must
// invoke the completion directly.
//
if (Error != WSA_IO_PENDING)
{
QueryCompleteCallback(Error, 0, &QueryContext.QueryOverlapped);
goto exit;
}
//
// Wait for query completion for 5 seconds and cancel the query if it has
// not yet completed.
//
if (WaitForSingleObject(QueryContext.CompleteEvent,
QueryTimeout) == WAIT_TIMEOUT )
{
//
// Cancel the query: Note that the GetAddrInfoExCancelcancel call does
// not block, so we must wait for the completion routine to be invoked.
// If we fail to wait, WSACleanup() could be called while an
// asynchronous query is still in progress, possibly causing a crash.
//
wprintf(L"The query took longer than %d seconds to complete; "
L"cancelling the query...\n", QueryTimeout/1000);
GetAddrInfoExCancel(&CancelHandle);
WaitForSingleObject(QueryContext.CompleteEvent,
INFINITE);
}
exit:
if (IsWSAStartupCalled)
{
WSACleanup();
}
if (QueryContext.CompleteEvent)
{
CloseHandle(QueryContext.CompleteEvent);
}
return Error;
}
//
// Callback function called by Winsock as part of asynchronous query complete
//
VOID
WINAPI
QueryCompleteCallback(
_In_ DWORD Error,
_In_ DWORD Bytes,
_In_ LPOVERLAPPED Overlapped
)
{
PQUERY_CONTEXT QueryContext = NULL;
PADDRINFOEX QueryResults = NULL;
WCHAR AddrString[MAX_ADDRESS_STRING_LENGTH];
DWORD AddressStringLength;
UNREFERENCED_PARAMETER(Bytes);
QueryContext = CONTAINING_RECORD(Overlapped,
QUERY_CONTEXT,
QueryOverlapped);
if (Error != ERROR_SUCCESS)
{
wprintf(L"ResolveName failed with %d\n", Error);
goto exit;
}
wprintf(L"ResolveName succeeded. Query Results:\n");
QueryResults = QueryContext->QueryResults;
while(QueryResults)
{
AddressStringLength = MAX_ADDRESS_STRING_LENGTH;
WSAAddressToString(QueryResults->ai_addr,
(DWORD)QueryResults->ai_addrlen,
NULL,
AddrString,
&AddressStringLength);
wprintf(L"Ip Address: %s\n", AddrString);
QueryResults = QueryResults->ai_next;
}
exit:
if (QueryContext->QueryResults)
{
FreeAddrInfoEx(QueryContext->QueryResults);
}
//
// Notify caller that the query completed
//
SetEvent(QueryContext->CompleteEvent);
return;
}
Nomi di dominio internazionalizzati
I nomi host Internet in genere sono costituiti da un set di caratteri molto limitato:- Lettere ASCII maiuscole e minuscole dell'alfabeto inglese.
- Cifre comprese tra 0 e 9.
- Caratteri trattini ASCII.
Con la crescita di Internet, c'è una crescente necessità di identificare i nomi host Internet per altre lingue non rappresentati dal set di caratteri ASCII. Gli identificatori che facilitano questa necessità e consentono a caratteri non ASCII (Unicode) di essere rappresentati come stringhe di caratteri ASCII speciali sono noti come nomi di dominio internazionalizzati (IDN). Un meccanismo denominato Internationalizing Domain Names in Applications (IDNA) viene usato per gestire gli IDN in modo standard. Le specifiche per IDN e IDNA sono documentate in RFC 3490, RTF 5890 e RFC 6365 pubblicate da Internet Engineering Task Force (IETF).
In Windows 8 e Windows Server 2012 la funzione GetAddrInfoEx fornisce il supporto per l'analisi dei nomi di dominio internazionalizzati (IDN) applicata al nome passato nel parametro pName . Winsock esegue codifica e conversione punycode/IDN. Questo comportamento può essere disabilitato usando il flag AI_DISABLE_IDN_ENCODING descritto di seguito.
In Windows 7 e Windows Server 2008 R2 o versioni precedenti, la funzione GetAddrInfoEx non fornisce attualmente il supporto per l'analisi IDN applicata al nome passato nel parametro pName . La versione a caratteri wide della funzione GetAddrInfoEx non usa Punycode per convertire un formato IDN Punycode come per RFC 3490. La versione a caratteri wide della funzione GetAddrInfoEx durante la query DNS codifica il nome Unicode in formato UTF-8, il formato usato dai server DNS Microsoft in un ambiente aziendale.
Diverse funzioni in Windows Vista e versioni successive supportano la conversione tra le etichette Unicode in un IDN nei relativi equivalenti ASCII. La rappresentazione risultante di ogni etichetta Unicode contiene solo caratteri ASCII e inizia con il prefisso xn-- se l'etichetta Unicode contiene tutti i caratteri non ASCII. Il motivo per questo è supportare i server DNS esistenti su Internet, poiché alcuni strumenti e server DNS supportano solo caratteri ASCII (vedere RFC 3490).
La funzione IdnToAscii usa Punycode per convertire un IDN nella rappresentazione ASCII della stringa Unicode originale usando l'algoritmo standard definito in RFC 3490. La funzione IdnToUnicode converte il formato ASCII di un IDN nella normale sintassi di codifica Unicode UTF-16. Per altre informazioni e collegamenti agli standard correlati, vedere Gestione dei nomi di dominio internazionalizzati (IDN).
La funzione IdnToAscii può essere usata per convertire un nome IDN in un modulo ASCII che può quindi essere passato nel parametro pName alla funzione GetAddrInfoEx quando viene usata la versione ASCII di questa funzione (quando UNICODE e _UNICODE non sono definiti). Per passare questo nome IDN alla funzione GetAddrInfoEx quando viene usata la versione a caratteri wide di questa funzione (quando è definito UNICODE o _UNICODE), è possibile usare la funzione MultiByteToWideChar per convertire la stringa CHAR in una stringa WCHAR .
Uso di ai_flags nel parametro hint
I flag nel membro ai_flags della struttura addrinfoex facoltativa fornita nel parametro hint modificano il comportamento della funzione.
Questi bit di flag sono definiti nel file di intestazione Ws2def.h nel Microsoft Windows Software Development Kit (SDK) per Windows 7. Questi bit di flag sono definiti nel file di intestazione Ws2tcpip.h in Windows SDK per Windows Server 2008 e Windows Vista. Questi bit di flag sono definiti nel file di intestazione Ws2tcpip.h nel Platform Software Development Kit (SDK) per Windows Server 2003 e Windows XP.
I bit di flag possono essere una combinazione dei seguenti:
Bit di flag | Descrizione |
---|---|
AI_PASSIVE |
L'impostazione del flag di AI_PASSIVE indica che il chiamante intende usare la struttura di indirizzi socket restituita in una chiamata alla funzione di associazione . Quando il flag di AI_PASSIVE è impostato e pName è un puntatore NULL , la parte dell'indirizzo IP della struttura di indirizzi socket è impostata su INADDR_ANY per indirizzi IPv4 e IN6ADDR_ANY_INIT per gli indirizzi IPv6.
Quando il flag AI_PASSIVE non è impostato, la struttura degli indirizzi socket restituita è pronta per una chiamata alla funzione di connessione per un protocollo orientato alla connessione o pronta per una chiamata alla connessione,all'invio o all'invio di funzioni per un protocollo senza connessione. Se il parametro pName è un puntatore NULL in questo caso, la parte dell'indirizzo IP della struttura degli indirizzi socket è impostata sull'indirizzo di loopback. |
AI_CANONNAME |
Se non viene usato né AI_CANONNAME né AI_NUMERICHOST , la funzione GetAddrInfoEx tenta la risoluzione. Se viene passata una stringa letterale GetAddrInfoEx tenta di convertire la stringa e se viene passato un nome host alla funzione GetAddrInfoEx tenta di risolvere il nome in un indirizzo o più indirizzi.
Quando il bit di AI_CANONNAME è impostato, il parametro pName non può essere NULL. In caso contrario, la funzione GetAddrInfoEx avrà esito negativo con WSANO_RECOVERY. Quando il AI_CANONNAME bit è impostato e la funzione GetAddrInfoEx restituisce esito positivo, il membro ai_canonname nel parametro ppResult punta a una stringa con terminazione NULL contenente il nome canonico del nodo specificato.
Nota La funzione GetAddrInfoEx può restituire esito positivo quando il flag di AI_CANONNAME è impostato, ma il membro ai_canonname nella struttura addrinfo associata è NULL. Pertanto, l'uso consigliato del flag di AI_CANONNAME include test se il membro ai_canonname nella struttura addrinfoex associata è NULL.
|
AI_NUMERICHOST | Quando viene impostato AI_NUMERICHOST bit, il parametro pName deve contenere una stringa di indirizzo host numerico non NULL , altrimenti viene restituito l'errore EAI_NONAME . Questo flag impedisce la chiamata di un servizio di risoluzione dei nomi. |
AI_NUMERICSERV |
Quando viene impostato il AI_NUMERICSERV bit, il parametro pServiceName deve contenere un numero di porta numerica non NULL , altrimenti viene restituito l'errore di EAI_NONAME . Questo flag impedisce la chiamata di un servizio di risoluzione dei nomi.
Il flag di AI_NUMERICSERV è definito in Windows SDK per Windows Vista e versioni successive. Il flag AI_NUMERICSERV non è supportato dai provider Microsoft. |
AI_ALL |
Se il bit di AI_ALL è impostato, viene effettuata una richiesta per indirizzi IPv6 e indirizzi IPv4 con AI_V4MAPPED.
Il flag di AI_ALL viene definito in Windows SDK per Windows Vista e versioni successive. Il flag di AI_ALL è supportato in Windows Vista e versioni successive. |
AI_ADDRCONFIG |
Se il bit di AI_ADDRCONFIG è impostato, GetAddrInfoEx risolverà solo se è configurato un indirizzo globale. Se viene specificato AI_ADDRCONFIG flag, gli indirizzi IPv4 verranno restituiti solo se un indirizzo IPv4 è configurato nel sistema locale e gli indirizzi IPv6 verranno restituiti solo se un indirizzo IPv6 è configurato nel sistema locale. L'indirizzo di loopback IPv4 o IPv6 non è considerato un indirizzo globale valido.
Il flag AI_ADDRCONFIG è definito in Windows SDK per Windows Vista e versioni successive. Il flag AI_ADDRCONFIG è supportato in Windows Vista e versioni successive. |
AI_V4MAPPED |
Se il bit di AI_V4MAPPED è impostato e una richiesta per gli indirizzi IPv6 ha esito negativo, viene eseguita una richiesta di servizio dei nomi per gli indirizzi IPv4 e questi indirizzi vengono convertiti in formato indirizzi IPv4 mappati.
Il flag di AI_V4MAPPED viene definito in Windows SDK per Windows Vista e versioni successive. Il flag AI_V4MAPPED è supportato in Windows Vista e versioni successive. |
AI_NON_AUTHORITATIVE |
Se il bit di AI_NON_AUTHORITATIVE è impostato, il provider di spazi dei nomi NS_EMAIL restituisce risultati autorevoli e non autorevoli. Se il bit di AI_NON_AUTHORITATIVE non è impostato, il provider di spazi dei nomi NS_EMAIL restituisce solo risultati autorevoli.
Il flag AI_NON_AUTHORITATIVE viene definito in Windows SDK per Windows Vista e versioni successive. Il flag AI_NON_AUTHORITATIVE è supportato in Windows Vista e versioni successive e si applica solo allo spazio dei nomi NS_EMAIL . |
AI_SECURE |
Se il bit di AI_SECURE è impostato, il provider di spazi dei nomi NS_EMAIL restituirà i risultati ottenuti con sicurezza avanzata per ridurre al minimo il possibile spoofing.
Il flag AI_SECURE è definito in Windows SDK per Windows Vista e versioni successive. Il flag AI_SECURE è supportato in Windows Vista e versioni successive e si applica solo allo spazio dei nomi NS_EMAIL . |
AI_RETURN_PREFERRED_NAMES |
Se la AI_RETURN_PREFERRED_NAMES è impostata, non deve essere specificato alcun nome nel parametro pName . Il provider di spazi dei nomi NS_EMAIL restituirà nomi preferiti per la pubblicazione.
Il flag AI_RETURN_PREFERRED_NAMES viene definito in Windows SDK per Windows Vista e versioni successive. Il flag di AI_RETURN_PREFERRED_NAMES è supportato in Windows Vista e versioni successive e si applica solo allo spazio dei nomi NS_EMAIL . |
AI_FQDN |
Se la AI_FQDN è impostata e viene specificato un nome flat (etichetta singola), GetAddrInfoEx restituirà il nome di dominio completo a cui il nome verrà risolto. Il nome di dominio completo viene restituito nel membro ai_canonname nella struttura addrinfoex associata. Questo è diverso dal flag di bit AI_CANONNAME che restituisce il nome canonico registrato in DNS, che può essere diverso dal nome di dominio completo a cui è stato risolto il nome flat.
Quando il bit di AI_FQDN è impostato, il parametro pName non può essere NULL. In caso contrario, la funzione GetAddrInfoEx avrà esito negativo con WSANO_RECOVERY. In Windows 8 e Windows Server 2012 è possibile impostare sia i bit AI_FQDN che i bit di AI_CANONNAME . Se la funzione GetAddrInfoEx viene chiamata con i bit di AI_FQDN e AI_CANONNAME , il parametro ppResult restituisce un puntatore a una struttura addrinfoex2 , non una struttura addrinfoex . In Windows 7 e Windows Server 2008 R2 è possibile impostare solo uno dei bit di AI_FQDN e AI_CANONNAME . La funzione GetAddrInfoEx avrà esito negativo se entrambi i flag sono presenti con EAI_BADFLAGS. Windows 7: Il flag AI_FQDN è definito in Windows SDK per Windows 7 e versioni successive. Il flag AI_FQDN è supportato in Windows 7 e versioni successive. |
AI_FILESERVER |
Se il AI_FILESERVER è impostato, si tratta di un hint per il provider di spazi dei nomi in cui viene eseguita la query del nome host nello scenario di condivisione file. Il provider di spazi dei nomi può ignorare questo hint.
Windows 7: Il flag AI_FILESERVER è definito in Windows SDK per Windows 7 e versioni successive. Il flag di AI_FILESERVER è supportato in Windows 7 e versioni successive. |
AI_DISABLE_IDN_ENCODING |
Se la AI_DISABLE_IDN_ENCODING è impostata, questa disabilita la codifica nome di dominio internazionale automatica usando Punycode nelle funzioni di risoluzione dei nomi denominate dalla funzione GetAddrInfoEx .
Windows 8: Il flag AI_DISABLE_IDN_ENCODING è definito in Windows SDK per Windows 8 e versioni successive. Il flag AI_DISABLE_IDN_ENCODING è supportato in Windows 8 e versioni successive. |
Nota
L'intestazione ws2tcpip.h definisce GetAddrInfoEx come alias che seleziona automaticamente la versione ANSI o Unicode di questa funzione in base alla definizione della costante preprocessore UNICODE. La combinazione dell'utilizzo dell'alias di codifica neutrale con il codice che non è neutrale dalla codifica può causare errori di corrispondenza che causano errori di compilazione o runtime. Per altre informazioni, vedere Convenzioni per i prototipi di funzione.
Requisiti
Requisito | Valore |
---|---|
Client minimo supportato | Windows XP [app desktop | App UWP] |
Server minimo supportato | Windows Server 2008 [app desktop | App UWP] |
Piattaforma di destinazione | Windows |
Intestazione | ws2tcpip.h |
Libreria | Ws2_32.lib |
DLL | Ws2_32.dll |