Поскольку я не получил ответа на свой предыдущий вопрос, я перефразирую его.
Какой порядок IP-адресов (в случае, когда IP-адреса привязаны к одному интерфейсу) используется при выполнении gethostbyname () с использованием имени ПК (имя NetBIOS)?
У меня есть этот код:
#include <iostream>
#include <winsock.h>
#pragma comment(lib, "Ws2_32.lib")
int main()
{
char hostname[255];
struct hostent *he;
struct in_addr **addr_list;
WSAData data;
WSAStartup(MAKEWORD(2, 2), &data);
gethostname(hostname, 255);
std::cout << "Host name: " << hostname << std::endl;
if ((he = gethostbyname(hostname)) == NULL) {
std::cout << "gethostbyname error" << std::endl;
} else {
std::cout << "IP addresses: " << std::endl;
addr_list = (struct in_addr **)he->h_addr_list;
for(int i = 0; addr_list[i] != NULL; i++) {
std::cout << inet_ntoa(*addr_list[i]) << std::endl;
}
}
std::cin.get();
}
И это дает мне разные результаты на Windows Server 2012 и Windows Server 2008 / Windows 7. На моем домашнем ПК с Windows 7 используется возрастающий порядок:
Host name: SplattWin
IP addresses:
192.168.1.140
192.168.3.1
192.168.3.2
192.168.3.3
192.168.3.4
Однако на Windows Server 2012 он дает мне IP-адреса в порядке убывания:
Host name: WinServ
IP addresses:
1.1.1.4
1.1.1.3
1.1.1.2
1.1.1.1
Есть ли способ изменить его порядок? Я попробовал флаг skipassource, когда добавил эти IP-адреса, но в этом случае он не работает.
У меня есть стороннее программное обеспечение, которое использует gethostname (), а затем gethostbyname (), чтобы определить свой собственный IP-адрес (он занимает первое место в списке). И очень жаль, что вам нужно менять настройки и клиентскую часть каждый раз, когда вы добавляете новый IP-адрес в вашу систему.
Порядок IP-адресов определяется Windows на основе приоритетов интерфейса и тому подобное. Не существует стандартного правила, которое бы перекрывало границы компьютеров или версий Windows. Вы должны рассматривать список вывода как случайный и самостоятельно переупорядочивать IP-адреса в соответствии с вашими потребностями. Например:
#include <iostream>
#include <vector>
#include <algorithm>
#include <winsock.h>
#pragma comment(lib, "Ws2_32.lib")
bool SortInAddr(const in_addr &a, const in_addr &b)
{
return (a.S_un.S_addr < b.S_un.S_addr);
}
int main()
{
WSAData data;
WSAStartup(MAKEWORD(2, 2), &data);
char hostname[256] = {0};
if (gethostname(hostname, 255) == SOCKET_ERROR)
{
std::cout << "gethostname error: " << WSAGetLastError() << std::endl;
}
else
{
std::cout << "Host name: " << hostname << std::endl;
struct hostent *he = gethostbyname(hostname);
if (he == NULL)
{
std::cout << "gethostbyname error: " << WSAGetLastError() << std::endl;
}
else if (he->h_length != sizeof(in_addr))
{
std::cout << "gethostbyname did not return IPv4 addresses" << std::endl;
}
else
{
std::vector<in_addr> addrs;
struct in_addr **addr_list = (struct in_addr **)(he->h_addr_list);
for(int i = 0; addr_list[i] != NULL; ++i)
{
addrs.push_back(*(addr_list[i]));
}
if (addrs.size() > 1)
{
std::sort(addrs.begin(), addrs.end(), SortInAddr);
}
std::cout << "IPv4 addresses: " << std::endl;
for(std::vector<in_addr>::iterator iter = addrs.begin();
iter != addrs.end();
++iter)
{
std::cout << inet_ntoa(addrs[i]) << std::endl;
}
}
}
WSACleanup();
std::cin.get();
}
Как говорится, не используйте gethostbyname()
(или же getaddrinfo()
) перечислять локальные интерфейсы машины. Такие функции не предназначены для этой цели. использование GetAdaptersInfo()
или же GetAdaptersAddresses()
вместо. Они специально предназначены для перечисления локальных интерфейсов и дают вам гораздо более подробную информацию об интерфейсах.