Funzione GetAddrInfoExA (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 GetAddrInfoExA(
[in, optional] PCSTR pName,
[in, optional] PCSTR pServiceName,
[in] DWORD dwNameSpace,
[in, optional] LPGUID lpNspId,
[in, optional] const ADDRINFOEXA *hints,
[out] PADDRINFOEXA *ppResult,
[in, optional] timeval *timeout,
[in, optional] LPOVERLAPPED lpOverlapped,
[in, optional] LPLOOKUPSERVICE_COMPLETION_ROUTINE lpCompletionRoutine,
[out, optional] LPHANDLE lpNameHandle
);
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 con estensione decimale o un indirizzo esadecimale IPv6.
[in, optional] pServiceName
Puntatore a una stringa con terminazione NULL facoltativa che contiene un nome del 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 dalla Internet Engineering Task Force (IETF) come porta predefinita utilizzata 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 di spazio dei nomi facoltativo che determina quali provider di spazi dei nomi vengono sottoposti a query. Il passaggio di un identificatore specifico dello spazio dei nomi comporta solo provider di spazi dei nomi che supportano la query dello spazio dei nomi specificato. Se si specifica NS_ALL , tutti i provider di spazi dei nomi installati e attivi verranno sottoposti a query.
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. Altri provider di spazi dei nomi possono essere installati, 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 query nel caso in cui più provider di spazi dei nomi siano registrati in un singolo spazio dei nomi, ad esempio NS_DNS. Il passaggio del GUID per un provider di spazi dei nomi specifico comporta solo la query del provider di spazi dei nomi specificato. La funzione WSAEnumNameSpaceProviders può essere chiamata per recuperare il GUID per un provider di spazi dei nomi.
[in, optional] hints
Puntatore a una struttura addrinfoex che fornisce hint 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 le osservazioni.
[out] ppResult
Puntatore a un elenco collegato di una o più strutture addrinfoex che contengono informazioni sulla risposta sull'host.
[in, optional] timeout
Parametro facoltativo che indica il tempo, 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 poiché un'opzione di timeout non è supportata.
[in, optional] lpOverlapped
Puntatore facoltativo a una struttura sovrapposta usata 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 l'evento specificato da hEvent è stato impostato, il risultato dell'operazione può essere recuperato 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 poiché 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 è 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 puntatore 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 l'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 poiché le operazioni asincrone non sono supportate.
[out, optional] lpNameHandle
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 restituisce 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 poiché 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 non zero restituiti dalla funzione GetAddrInfoEx viene mappata al set di errori descritti dalle raccomandazioni di Internet Engineering Task Force (IETF). La tabella seguente mostra questi codici di errore e i relativi equivalenti WSA. È consigliabile usare i codici di errore WSA, poiché offrono informazioni di errore familiari e complete per i programmatori Winsock.
Valore di errore | WSA equivalente | 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 lpNameHandle 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 lpNameHandle 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 suggerimenti sul tipo di socket supportato tramite una struttura addrinfoex a cui punta il parametro pHints . Quando si usa 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.
- Il valore zero per ai_socktype indica che il chiamante accetterà qualsiasi tipo di socket.
- Il valore 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 utilizzata per convertire una rappresentazione di stringa di testo di un indirizzo IP in una struttura addrinfoex contenente una struttura sockaddr per l'indirizzo IP e altre informazioni. Per essere usata in questo modo, la stringa a cui punta il parametro pName deve contenere una rappresentazione testuale di un indirizzo IP e la struttura addrinfoex a cui punta il parametro pHints deve essere impostato il flag AI_NUMERICHOST nel membro ai_flags . La stringa a cui punta il parametro pName può contenere una rappresentazione testuale di un indirizzo IPv4 o 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 esegue la registrazione anche per lo spazio dei nomi NS_DNS. Quando il parametro dwNameSpace è impostato su un valore (ad esempio, NS_DNS) e il parametro lpNspId è NULL, i risultati restituiti dalla funzione GetAddrInfoEx sono i risultati uniti da tutti i provider di spazi dei nomi che eseguono la registrazione per lo spazio dei nomi specificato con risultati duplicati eliminati. Il parametro lpNspId deve essere impostato sul GUID del provider dello spazio dei nomi specifico se deve essere eseguita una query solo su un singolo provider dello spazio 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 punta 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 lpNameHandle 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.
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 canonici 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 sono in genere 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 rappresentate dal set di caratteri ASCII. Gli identificatori che facilitano questa esigenza e consentono la rappresentazione di caratteri non ASCII (Unicode) 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 IDN (Internationalized Domain Name) applicata al nome passato nel parametro pName . Winsock esegue la codifica e la 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 Punycode IDN in base a RFC 3490. La versione a caratteri wide della funzione GetAddrInfoEx durante l'esecuzione di 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 etichette Unicode in un IDN ai rispettivi equivalenti ASCII. La rappresentazione risultante di ogni etichetta Unicode contiene solo caratteri ASCII e inizia con il prefisso xn-- se l'etichetta Unicode contiene caratteri non ASCII. Il motivo è 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 ai progetti di standard correlati, vedere Gestione dei nomi di dominio internazionalizzati (IDN).For more information and links to related draft standards, see Handling Internationalized Domain Names (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 viene definito UNICODE o _UNICODE), è possibile usare la funzione MultiByteToWideChar per convertire la stringa CHAR in una stringa WCHAR .
Uso di ai_flags nel parametro hints
I flag nel membro ai_flags della struttura addrinfoex facoltativa fornita nel parametro hints 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 del flag possono essere una combinazione dei seguenti:
Flag Bits | Descrizione |
---|---|
AI_PASSIVE |
L'impostazione del flag AI_PASSIVE indica che il chiamante intende utilizzare la struttura di indirizzi socket restituita in una chiamata alla funzione di associazione . Quando il flag AI_PASSIVE è impostato e pName è un puntatore NULL , la parte dell'indirizzo IP della struttura degli indirizzi socket viene impostata su INADDR_ANY per gli indirizzi IPv4 e IN6ADDR_ANY_INIT per gli indirizzi IPv6.
Quando il flag di AI_PASSIVE non è impostato, la struttura di indirizzi socket restituita è pronta per una chiamata alla funzione di connessione per un protocollo orientato alla connessione o pronta per una chiamata alle funzioni connect, sendto o send per un protocollo senza connessione.When the AI_PASSIVE flag is not set, the returned socket address structure is ready for a connectionless protocol, or ready for a connect, sendto, or send functions for a connectionless protocol. Se il parametro pName è un puntatore NULL in questo caso, la parte dell'indirizzo IP della struttura di indirizzi socket viene 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 un nome host viene passato alla funzione GetAddrInfoEx tenta di risolvere il nome in un indirizzo o più indirizzi.
Quando il bit AI_CANONNAME è impostato, il parametro pName non può essere NULL. In caso contrario, la funzione GetAddrInfoEx avrà esito negativo con WSANO_RECOVERY. Quando il bit AI_CANONNAME è impostato e la funzione GetAddrInfoEx restituisce esito positivo, il membro ai_canonname nel parametro ppResult punta a una stringa con terminazione NULL che contiene il nome canonico del nodo specificato. Nota La funzione GetAddrInfoEx può restituire l'esito positivo quando il flag AI_CANONNAME è impostato, ma il membro ai_canonname nella struttura addrinfo associata è NULL. Pertanto, l'uso consigliato del flag di AI_CANONNAME include il test se il membro ai_canonname nella struttura addrinfoex associata è NULL.
|
AI_NUMERICHOST | Quando il bit AI_NUMERICHOST è impostato, il parametro pName deve contenere una stringa di indirizzo host numerico non NULL . In caso contrario, viene restituito l'errore EAI_NONAME . Questo flag impedisce la chiamata di un servizio di risoluzione dei nomi. |
AI_NUMERICSERV |
Quando il bit AI_NUMERICSERV è impostato, il parametro pServiceName deve contenere un numero di porta numerico non NULL . In caso contrario, viene restituito l'errore di EAI_NONAME . Questo flag impedisce la chiamata di un servizio di risoluzione dei nomi.
Il flag 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 AI_ALL è impostato, viene effettuata una richiesta per indirizzi IPv6 e indirizzi IPv4 con AI_V4MAPPED.
Il flag AI_ALL viene definito in Windows SDK per Windows Vista e versioni successive. Il flag AI_ALL è supportato in Windows Vista e versioni successive. |
AI_ADDRCONFIG |
Se il bit AI_ADDRCONFIG è impostato, GetAddrInfoEx verrà risolto solo se è configurato un indirizzo globale. Se viene specificato AI_ADDRCONFIG flag, gli indirizzi IPv4 verranno restituiti solo se è configurato un indirizzo IPv4 nel sistema locale e gli indirizzi IPv6 verranno restituiti solo se nel sistema locale è configurato un indirizzo IPv6. L'indirizzo di loopback IPv4 o IPv6 non è considerato un indirizzo globale valido.
Il flag AI_ADDRCONFIG viene 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 AI_V4MAPPED è impostato e una richiesta per gli indirizzi IPv6 ha esito negativo, viene effettuata una richiesta di servizio dei nomi per gli indirizzi IPv4 e questi indirizzi vengono convertiti in formato indirizzo IPv4 mappato a IPv6.
Il flag 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 AI_NON_AUTHORITATIVE è impostato, il provider dello spazio dei nomi NS_EMAIL restituisce risultati autorevoli e non autorevoli. Se il bit AI_NON_AUTHORITATIVE non è impostato, il provider dello spazio 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 AI_SECURE è impostato, il provider dello spazio dei nomi NS_EMAIL restituirà i risultati ottenuti con sicurezza avanzata per ridurre al minimo il possibile spoofing.
Il flag AI_SECURE viene 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 il AI_RETURN_PREFERRED_NAMES è impostato, non deve essere specificato alcun nome nel parametro pName . Il provider dello spazio dei nomi NS_EMAIL restituirà i nomi preferiti per la pubblicazione.
Il flag AI_RETURN_PREFERRED_NAMES viene definito in Windows SDK per Windows Vista e versioni successive. Il flag 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 da AI_CANONNAME flag di bit che restituisce il nome canonico registrato in DNS, che può essere diverso dal nome di dominio completo risolto dal nome flat.
Quando il bit 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 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 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 suggerimento per il provider dello spazio dei nomi su cui viene eseguita la query sul nome host sottoposto a query nello scenario di condivisione file. Il provider dello spazio dei nomi può ignorare questo hint.
Windows 7: Il flag AI_FILESERVER viene definito in Windows SDK per Windows 7 e versioni successive. Il flag AI_FILESERVER è supportato in Windows 7 e versioni successive. |
AI_DISABLE_IDN_ENCODING |
Se il AI_DISABLE_IDN_ENCODING è impostato, questa opzione disabilita la codifica automatica dei nomi di dominio internazionale usando Punycode nelle funzioni di risoluzione dei nomi chiamate dalla funzione GetAddrInfoEx .
Windows 8: Il flag AI_DISABLE_IDN_ENCODING viene 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 del preprocessore UNICODE. La combinazione dell'utilizzo dell'alias indipendente dalla codifica con il codice che non è indipendente dalla codifica può causare mancate corrispondenze che generano errori di compilazione o di runtime. Per altre informazioni, vedere Convenzioni per i prototipi di funzioni.
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 |