【发布时间】:2019-08-30 19:15:18
【问题描述】:
问题的一点背景:
我最近对 Microsoft 和套接字绑定有过一次濒死体验。我正在测试生产代码,其中一台测试 PC 一直失败。我最终建议bind() 函数中存在错误,这是最古老的函数之一。
我提交了错误(请参阅 Visual Studio 的开发人员社区反馈论坛中的 CAsyncSocket Create's bind implementation has a bug),但被移交给了 Windows 团队(请参阅他们的反馈中心中的“__imp_bind 实现有一个长期存在的情境错误”),谁从来没有做过任何事情。
由于我无法调试 bind(),并且 Microsoft 拒绝提供帮助,经过 2 周的开发工作后,我最终发现,有问题的测试机器启用了 Hyper-V,而我的接口解析代码正在拾取这个虚假的AF_INET 地址并解析它而不是真实的 IP 地址。
我不能指望我的客户仅仅为了运行我的软件而关闭不需要的 Hyper-V 功能,因此我需要使我的解析代码更加精细。
我的问题:
我需要做的是能够获取特定地址的详细名称,例如ipconfig /all。我可以看到其他人也问过这个问题,比如 Ivan 的 how to determine interface name 和 tez 的 Linux getting all network interface names。 Ivan 的答案是使用getsockname(),tez 的答案是使用if_nameindex()。两者都没有返回详细的接口名称,如 ipconfig 所示。
那么,有人知道那会是什么函数调用吗?
【问题讨论】:
-
在 Windows 上,查看
GetAdaptersInfo()(XP 及更早版本)和GetAdaptersAddresses()(Vista 及更高版本)、GetInterfaceInfo()等。您只能从getsockname()获取套接字的真实本地 IP在它被bind()ed 到特定IP 之后,或者在accept()ed 或connect()ed 如果绑定到通配符IP 之后,然后您可以在地址表中查找IP 以找到其接口索引,然后在接口表中查找该索引以获取其可读名称。 -
话虽如此,Hyper-V 究竟是什么原因破坏了您的代码?你能详细说明一下吗?世界上 99% 的套接字代码并没有对 Hyper-V 做任何特别的事情,而且它“正常工作”,那么 Hyper-V 在您的特定环境中到底是什么破坏了?你能提供一个不适合你的minimal reproducible example 吗?您的代码如何设置套接字?期望的结果是什么?实际结果如何?
-
GetAdaptersAddresses() 会正常工作。我的接口解析代码不是很复杂,只是抓取了第一个解析的 AF_INET 接口。当然,现在 Ipv6 出现了,还有更多无法解释的接口出现,例如 Npcap Loopback Adapter 和 Hyper-V... 然后 family 不足以解决问题。问题不是 bind() 中的错误,而是在解决时无法更好地区分。一旦我使用 GetAdaptersAddresses() 做到这一点,幻像 bind() 问题就会消失。
-
那么,您正试图通过接口名称
bind()一个套接字?为什么不直接通过IPbind()它,然后要求用户提供正确的IP才能使用?一个网络接口可以分配有多个 IP,因此仅一个名称可能是不够的,除非您bind()为该接口实际拥有的每个 IP 提供一个单独的套接字。 -
问题出现在我的华硕测试机上,但没有出现在戴尔测试机上。这两台机器都打开了 Hyper-V。经过大量调试后,我才意识到正在为华硕解决错误的接口。如果我没记错的话,在华硕上,链表接口顺序与戴尔上的不同,这使我的顺序解析接口代码出错,其中 Hyper-V 接口首先出现在华硕上。为什么两个硬件平台的链表接口顺序不同,我不知道。但很明显,我的代码不应该对这种变化敏感。
标签: sockets mfc bind casyncsocket