spl*_*tru 6 c++ ip winsock gethostbyname windows-server
由于我之前的问题没有答案,因此我将其重述。
使用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();
}
Run Code Online (Sandbox Code Playgroud)
在Windows Server 2012和Windows Server 2008 / Windows 7上,它给我不同的结果。在装有Windows 7的家用PC上,使用升序:
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
Run Code Online (Sandbox Code Playgroud)
但是,在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
Run Code Online (Sandbox Code Playgroud)
有什么办法可以重新排序吗?添加这些IP地址时,我尝试过skipassource标志,但在这种情况下似乎不起作用。
我有使用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();
}
Run Code Online (Sandbox Code Playgroud)
话虽如此,不要使用gethostbyname()(或getaddrinfo()) 来枚举计算机的本地接口。此类功能并非用于此目的。使用GetAdaptersInfo()或GetAdaptersAddresses()代替。它们专门用于枚举本地接口,并为您提供有关接口的更多详细信息。