如何在Winsock API中从没有gethostbyname的url获取IP地址



我想从URL中获取IP地址。我在谷歌上找到了答案,它只有gethostbyname()功能解决方案,但MSDN说这个功能已经不用了。

我尝试使用getaddressinfo()getnameinfo()(MSDN中的示例(,它只返回255.255.255。

我该怎么办?谢谢大家!

gethostbyname()确实不推荐使用,getaddrinfo()是现在使用的正确函数。

您需要解析URL以提取其主机名,以及可选的端口号(请参阅InternetCrackUrl()或其他类似的解析器(,然后将该主机名/端口传递给getaddrinfo()。它将以sockaddr_in(IPv4(或sockaddr_in6(IPv6(格式返回一个addrinfo结构的链接列表,其中包含分配给主机的每个IP地址。

如果您需要这些IP作为字符串,您可以使用inet_ntop()RtlIpv4AddressToString()/RtlIpv6AddressToString()、带有NI_NUMERICHOST标志的getnameinfo()等。

地址是通过域名而不是URL获得的。

以下是从域名中获取IPv6和IPv4地址的两个函数。

函数参数是domain_name-域名(例如dns.google(。结果是local_internet_name-IPv6或IPv4地址的列表,取决于所使用的函数(例如{[8.8.8.8],[8.8.4.4]}用于dns.google域的IPv4地址(返回值是属性";地址已找到或未找到";(真与假(。

domain_name_to_internet_6_name

domain_name_to_internet_4_name

函数使用MFC字符串类、C++标准库、Windows DNS函数和网络函数。

测试控制台程序的输出示例:

2001:4860:4860::88882001:4860:4860::88448.8.8.88.8.4.4

D: \Projects\DNS_Test\Debug\DNS_Test.exe(进程14740(已退出,代码为0。按任意键关闭此窗口。

要在Microsoft Visual Studio中为Windows创建可执行文件,您需要从;用于Windows的控制台应用程序";模板,并将项目属性设置为";使用MFC库";(作为共享库或静态库(

以下是控制台程序的代码:

#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 -- %srn", 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 -- %srn", 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;
}
}
}

最新更新