Порядок IP-адресов в функции gethostbyname

Поскольку я не получил ответа на свой предыдущий вопрос, я перефразирую его.

Какой порядок 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-адрес в вашу систему.

4

Решение

Порядок 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() вместо. Они специально предназначены для перечисления локальных интерфейсов и дают вам гораздо более подробную информацию об интерфейсах.

2

Другие решения


По вопросам рекламы [email protected]