gethostbyname 函数中的 IP 地址顺序
Posted
技术标签:
【中文标题】gethostbyname 函数中的 IP 地址顺序【英文标题】:IP address order in gethostbyname function 【发布时间】:2015-01-09 09:59:18 【问题描述】:由于我之前的问题没有得到答案,所以我会改写它。
使用 PC 名称(NetBios 名称)执行 gethostbyname() 时,使用什么 IP 地址顺序(如果 IP 地址绑定到一个接口)?
我有这个代码:
#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
有没有办法重新排序?我在添加这些 IP 地址时尝试了 skipassource 标志,但在这种情况下似乎不起作用。
我有第三方软件使用 gethostname() 后跟 gethostbyname() 来确定它自己的 IP 地址(它从列表中首先获取)。每次向系统添加新 IP 地址时都需要更改设置和客户端,这真是令人沮丧。
【问题讨论】:
【参考方案1】: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()
。它们专门用于枚举本地接口,并为您提供有关接口的更详细信息。
【讨论】:
正如我所说,我有我无法控制的第 3 方软件,即使用 gethostbyname() 返回的列表中的第一个 IP。问题是如何在一台特定的机器上重新排序 IP。不过还是谢谢你的回答。 您对 Windows 如何决定对其 IP 地址进行排序没有太多/任何控制权。它更关心其路由表中 IP 的顺序及其优先级,然后是接口的顺序和其中的 IP 地址。您能做的最好的事情可能就是联系第 3 方,要求他们调整软件以在选择 IP 之前手动订购 IP,类似于我展示的内容。 我认为使用 gethostbyname/gethostname 钩子编写外部 dll 并注入/修补它比联系制造商更容易。这个软件真的很老了。不管怎样,谢谢你。他们改变了这种常见功能的行为,这很奇怪。gethostbyname()
从未用于枚举本地 IP,而是用于 DNS 查找。在处理 DNS 结果时,软件应该尝试连接到报告的每个 IP,直到连接成功。这只是多年来人们如何滥用gethostbyname()
的另一个例子,以及为什么存在其他枚举函数来替代这种滥用。但是,是的,在您的情况下,听起来需要绕道而行来重新排序报告的 IP。以上是关于gethostbyname 函数中的 IP 地址顺序的主要内容,如果未能解决你的问题,请参考以下文章
编程黑科技gethostbyname()函数:通过域名获取IP地址!
(高分)关于 gethostbyname函数的具体使用 谢谢