如何在 C++ 中读取 Windows 默认网关 IP 地址
Posted
技术标签:
【中文标题】如何在 C++ 中读取 Windows 默认网关 IP 地址【英文标题】:How to read Windows default Gateway IP address in C++ 【发布时间】:2013-02-27 17:34:22 【问题描述】:有人可以告诉我如何在 C++ 中读取默认的 Windows 网关 IP 地址。我可以使用 GetAdaptersInfo() 读取所有 IP 地址的列表,但不能读取默认网关 IP 地址。
GetAdaptersInfo( pAdapterInfo, &BufferLength );
// Iterate the network adapters and print their MAC address.
while( pAdapterInfo )
pAdapterInfo = pAdapterInfo->Next; // Get next adapter info
这是代码 sn-p 并想知道哪个字段为我提供了默认网关。我可以获取列表中每个 IP 地址的网关,但我需要默认网关 IP 地址。
想要这样做的最初原因是选择具有默认网关的 IP 的特定 MAC 地址(从一堆 MAC 地址中)。当我们在遍历列表时获得多个 MAC 地址时,我们认为最好的方法是选择具有默认网关的 IP 的 MAC 地址。此后我们改变了主意,将选择有线连接 MAC 地址。但我仍然很想知道如何获取默认网关,而不是遍历所有适配器。
【问题讨论】:
【参考方案1】:GetAdaptersInfo
给你这个:
网关列表
类型:IP_ADDR_STRING
此适配器的网关 IPv4 地址表示为 IP_ADDR_STRING 结构的链接列表。一个适配器可以有多个 分配给它的 IPv4 网关地址。该列表通常包含一个 此适配器的默认网关的 IPv4 地址的单个条目。
如果您无法从已有的GetAdaptersInfo
数据获取网关,您可能需要发布代码。
基本上,您可以通过在推荐提示符下运行 ipconfig /all
来“预览”此信息。您将看到每个接口都定义了网关,没有全局网关。 route print
为您获取路由,您可以看到它们具有优先级,这规定了是否有效使用了这个或那个网关:这取决于采用的路由。
【讨论】:
感谢您的 cmets。可能是我误解了它的工作方式。我在想会有一个 API 给我默认网关,而不是遍历整个列表。我的计划是找到默认GW,遍历整个列表,看看哪个IP地址使用了默认GW。【参考方案2】:由于您想使用 WINAPI,GetAdapterAddresses 可能是最好的选择。
GAA_FLAG_INCLUDE_GATEWAYS | GAA_FLAG_INCLUDE_ALL_INTERFACES | GAA_FLAG_SKIP_DNS_SERVER | GAA_FLAG_SKIP_MULTICAST
IP_ADAPTER_ADDRESSES 函数的文档是here。
【讨论】:
【参考方案3】:这种方式根本不起作用 - 设置窗口显示给定接口的默认网关,但没有整个系统的默认网关之类的东西。再次设置窗口将尝试提供帮助,并建议将一个或另一个网络接口设置为默认值,但如果您这样做,实际上会在routing table 中添加一个默认条目。问题是更高级的设置将使您能够根据目标地址使用不同的接口(甚至网关)。如果您希望您的默认网关用于通信某些特定地址,您可以使用GetBestRoute - 它会告诉您如果您想联系给定地址,您将使用哪个网关。如果您只想为您的计算机获得一个通用默认网关,您可能会尝试扫描路由表,但这是一件令人讨厌的事情,而且那里甚至可能没有被识别为单个默认网关的东西,可能有很多 - 无论如何,系统通常都会“正常工作”,但让你的程序发现它可能会变得很棘手。
总结一下:没有计算机范围的默认网关。桌面 Windows 通常以类似的方式设置,但这不是严格的要求。即使是这样,它也是使用较低级别的机制(路由表)完成的,并且读取它的配置可能会令人讨厌 - 我知道,我已经做到了;)
另一个想法 - 控制面板可能会将这些设置保存在注册表中的某个位置,以便系统能够在每次系统启动时配置网络。如果您发现这些在哪里,您可能无法获得 100% 面向网络的默认网关,但您肯定会获得用户在设置窗口中看到的值。我不知道在哪里可以找到这样的知识,我怀疑它没有发布,并作为实现细节保留 - 意味着它可以从一个版本到另一个版本,甚至有一些更大的更新/服务包。如果你这样做,它很可能无法在不同的 Windows 版本之间移植。
PS 为什么需要这个?为什么会有人需要这个?
【讨论】:
有根据的猜测:出于许可原因,他想要一个 MAC 地址,以便将激活码绑定到特定机器。由于通常有多个 MAC 地址,因此他需要一种一致的方式来选择一个特定的 MAC 地址。如果确实有默认网关这样的东西,关联适配器的MAC地址将是一个合理的选择。 @HarryJohnston 合理的选择?如果用户使用笔记本电脑并且有时通过电缆连接它 - 以获得更好的速度,但有时会在他的公寓周围徘徊,笔记本电脑在 wifi 上......他的默认网关 MAC 地址会发生什么?由于您可以更改 MAC,只要您的计算机位于不同的子网中,您就可以有效地欺骗您的许可软件。在这种情况下,我宁愿去找主板序列号。至少周围没有现成的方法。 好点; “首选默认网关”(即使它存在)将不是一个明智的标准,至少对于可能在笔记本电脑上运行的软件而言。不过,MAC 地址是传统的选择,我认为部分原因是并非所有主板都将序列号暴露给软件。作为系统管理员,我想说的是,如果有必要可以覆盖它是一个特性,而不是一个错误:如果客户因为紧急硬件更换导致许可失败而遭受额外的停机时间,他们很可能会生气(并且不能被覆盖)。 @HarryJohnston 所以如果我理解你的话,首先软件供应商实施许可系统以使用它的 MAC 地址将软件锁定到单台机器,然后硬件供应商使其可变以允许硬件更换。我看不出这种情况的意义所在。如果保持服务器运行并可能更改硬件非常重要,那么许可系统有什么用? PS 我知道更改 MAC 的主要原因是交换网络内可能发生冲突。 不需要(或不应该)能够更改 MAC 地址以避免冲突;烧入硬件的默认地址应该是唯一的。我相信该功能旨在允许 MAC 地址基于第 3 层地址; IP 不使用这个,但 DECNet 用于 IIRC。【参考方案4】:通常,您将使用 GetAdaptersInfo(根据 Roman R 的回答)或最好使用 GetAdapterAddresses(根据 specializt 的回答)来列出适配器,并且只有一个适配器会配置一个网关。但是,可以有多个默认网关,尽管它是not recommended。但是,在有多个默认网关的计算机上,我相信GetBestRoute 函数会告诉您当前正在使用哪个网关。请注意,这可能随时更改。
只有当多个适配器都配置了网关时,您才需要调用 GetBestRoute 来决定哪个默认网关最有可能用于任何给定的连接。请记住,如果有多个默认网关,则它们都不会被认为天生比其他网关“更好”;换句话说,在这种情况下,没有“默认网关”之类的东西,只有“默认网关”。
【讨论】:
此调用是否保证提供默认网关 IP? “路由打印”是否在内部使用相同的调用? 在我唯一可以玩的多宿主机器上,“路由打印”不显示当前正在使用哪个默认网关,它只列出每个适配器的默认网关,即,究竟是什么@ 987654323@给你。你在看什么? 最初的想法是从拥有默认网关的IP中获取MAC地址(从一堆MAC地址中)。当我们在遍历列表时获得多个 MAC 地址时,我们认为最好的方法是获取具有默认网关的 IP 的 MAC 地址。但现在我们改变主意,拿起有线连接的 MAC 地址。但我仍然很想知道如何获取默认网关而不是遍历所有适配器。 请停止假设 - 有 WINAPI 函数可用于获取所选/要选择的网关。 @specializt: 比如?以上是关于如何在 C++ 中读取 Windows 默认网关 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章
如何访问 C++ windows 10 应用程序中的默认线程池?
在 Linux 和 Windows 机器上使用 C++ 调度任务