I want to get IP Address from URL. I find the answer in google, it only has gethostbyname() function solution, but MSDN said that this function is not used anymore.
I try to use getaddressinfo() or getnameinfo() (the example in MSDN), it only returns 255.255.255.255.
How can I do? Thank all!
CodePudding user response:
gethostbyname() is indeed deprecated, and getaddrinfo() is the correct function to use now.
You need to parse the URL to extract its hostname, and optionally its port number (see InternetCrackUrl(), or other similar parser), then pass that hostname/port to getaddrinfo(). It will give you back a linked list of addrinfo structs containing each IP address assigned to the host, in sockaddr_in (IPv4) or sockaddr_in6 (IPv6) format.
If you need those IPs as strings, you can use inet_ntop(), RtlIpv4AddressToString()/RtlIpv6AddressToString(), getnameinfo() with the NI_NUMERICHOST flag, etc.
CodePudding user response:
Addresses are obtained by domain name, not by URL.
Here are two functions to get an IPv6 and IPv4 address from a domain name.
Functions parameter is domain_name - domain name (eg dns.google). The result is local_internet_name - a list of IPv6 or IPv4 addresses depending on the function used (e.g. {[8.8.8.8], [8.8.4.4]} for IPv4 addresses of the dns.google domain) The return value is the attribute "Addresses found or not found" (true and false).
domain_name_to_internet_6_name
domain_name_to_internet_4_name
The functions use the MFC string classes, the C standard library, Windows DNS functions, and network functions.
An example of the output from a test console program:
2001:4860:4860::8888 2001:4860:4860::8844 8.8.8.8 8.8.4.4
D:\Projects\DNS_Test\Debug\DNS_Test.exe (process 14740) exited with code 0. Press any key to close this window . . .
To create an executable for Windows, in Microsoft Visual Studio, you need to create a project from the "Console Application for Windows" template, and set the project properties to "Use MFC library" (as a shared library or as a static library)
Here's the code for a console program:
#include <afxwin.h>
#include <iostream>
#include <string>
#include <list>
#include <ws2tcpip.h>
#pragma comment(lib, "normaliz.lib")
#pragma comment(lib, "dnsapi.lib")
bool domain_name_to_internet_6_name(CStringW domain_name, std::list<CStringA>& local_internet_name)
{
const size_t CONST_MESSAGE_LENGTH = 500;
wchar_t local_domain_name_unicode[CONST_MESSAGE_LENGTH];
ZeroMemory(local_domain_name_unicode, sizeof(wchar_t) * CONST_MESSAGE_LENGTH);
if (IdnToAscii(0, domain_name, domain_name.GetLength(), local_domain_name_unicode, CONST_MESSAGE_LENGTH) == 0)
{
const int local_error_message_size = 500;
wchar_t local_error_message[local_error_message_size];
const int local_system_error_message_size = local_error_message_size - 250;
wchar_t local_system_error_message[local_system_error_message_size];
wcscpy_s(local_system_error_message, local_system_error_message_size, L"IdnToAscii finished with error");
CString local_time_string = CTime::GetCurrentTime().FormatGmt("%d/%m/%y %H:%M:%S GMT");
wsprintf((wchar_t*)local_error_message, L"Networking error -- %s -- %s\r\n", local_system_error_message, local_time_string.GetBuffer());
// В local_error_message находится текст с кодом сетевой ошибки при выполнении функции IdnToAscii
return false;
}
PDNS_RECORD ppQueryResults;
ZeroMemory(&ppQueryResults, sizeof(ppQueryResults));
if (DnsQuery_W(local_domain_name_unicode, DNS_TYPE_AAAA, 0, NULL, &ppQueryResults, NULL) == ERROR_SUCCESS)
{
for (PDNS_RECORD ptr = ppQueryResults; ptr != NULL; ptr = ptr->pNext)
{
if (ptr->wType == DNS_TYPE_AAAA)
{
if (ptr->wDataLength != 0)
{
char local_address_buffer[100];
inet_ntop(AF_INET6, &ptr->Data.AAAA.Ip6Address.IP6Byte, local_address_buffer, 100);
local_internet_name.push_back(local_address_buffer);
}
}
}
DnsFree(ppQueryResults, DnsFreeRecordList);
if (local_internet_name.size() != 0)
{
return true; // Адреса найдены
}
else
{
return false; // Адреса не найдены
}
return true;
}
return false;
}
bool domain_name_to_internet_4_name(CStringW domain_name, std::list<CStringA>& local_internet_name)
{
const size_t CONST_MESSAGE_LENGTH = 500;
wchar_t local_domain_name_unicode[CONST_MESSAGE_LENGTH];
ZeroMemory(local_domain_name_unicode, sizeof(wchar_t) * CONST_MESSAGE_LENGTH);
if (IdnToAscii(0, domain_name, domain_name.GetLength(), local_domain_name_unicode, CONST_MESSAGE_LENGTH) == 0)
{
const int local_error_message_size = 500;
wchar_t local_error_message[local_error_message_size];
const int local_system_error_message_size = local_error_message_size - 250;
wchar_t local_system_error_message[local_system_error_message_size];
wcscpy_s(local_system_error_message, local_system_error_message_size, L"IdnToAscii finished with error");
CString local_time_string = CTime::GetCurrentTime().FormatGmt("%d/%m/%y %H:%M:%S GMT");
wsprintf((wchar_t*)local_error_message, L"Networking error -- %s -- %s\r\n", local_system_error_message, local_time_string.GetBuffer());
// В local_error_message находится текст с кодом сетевой ошибки при выполнении функции IdnToAscii
return false;
}
PDNS_RECORD ppQueryResults;
ZeroMemory(&ppQueryResults, sizeof(ppQueryResults));
if (DnsQuery_W(local_domain_name_unicode, DNS_TYPE_A, 0, NULL, &ppQueryResults, NULL) == ERROR_SUCCESS)
{
for (PDNS_RECORD ptr = ppQueryResults; ptr != NULL; ptr = ptr->pNext)
{
if (ptr->wType == DNS_TYPE_A)
{
if (ptr->wDataLength != 0)
{
char local_address_buffer[100];
inet_ntop(AF_INET, &ptr->Data.A.IpAddress, local_address_buffer, 100);
local_internet_name.push_back(local_address_buffer);
}
}
}
DnsFree(ppQueryResults, DnsFreeRecordList);
if (local_internet_name.size() != 0)
{
return true; // Адреса найдены
}
else
{
return false; // Адреса не найдены
}
return true;
}
return false;
}
int main()
{
std::list<CStringA> local_internet_name_6;
if (domain_name_to_internet_6_name(CStringW(L"dns.google"), local_internet_name_6))
{
for (auto i = local_internet_name_6.begin(); i != local_internet_name_6.end(); i )
{
std::cout << *i << std::endl;
}
}
std::list<CStringA> local_internet_name_4;
if (domain_name_to_internet_4_name(CStringW(L"dns.google"), local_internet_name_4))
{
for (auto i = local_internet_name_4.begin(); i != local_internet_name_4.end(); i )
{
std::cout << *i << std::endl;
}
}
}
