我正在查看一些过时的代码,该代码使用getaddrinfo
和getnameinfo
来确定主机名信息,然后回到gethostname
和gethostbyname
if { {1}}失败。
现在,这对我来说似乎不对。我试图了解代码的意图,以便我可以提出建议。我不想在这里重新发布整个代码,因为它冗长而复杂,但我会尝试总结一下:
据我所知,此代码的要点是生成一个字符串,该字符串可供另一个进程用于连接到侦听套接字。这似乎不仅适用于本地进程,也适用于远程主机连接回此计算机。
所以有问题的代码基本上是在执行以下操作:
getnameinfo
- 这会获得getaddrinfo(node = NULL, service = port, hints.ai_flags = AI_PASSIVE, ai);
可能与socket()
一起使用的可能参数列表。bind()
。addrinfo
的{{1}},请致电ai_addr
以获取相关的主机名。addrinfo
,然后在结果上查找getnameinfo()
。我认为这有几个原因是错误的,但我想验证我的逻辑。首先,从一些实验来看,gethostname()
几乎总是在这里失败。我认为输入地址是未知的,因为它是一个侦听套接字,而不是目标,因此从这个角度来看它不需要有效的IP。然后,调用gethostbyname()
并将结果传递给getnameinfo()
几乎总是返回与gethostname()
相同的结果。换句话说,它只是验证本地主机名,对我来说似乎毫无意义。这是有问题的,因为它甚至不一定可以被远程主机使用,是吗?
不知何故,我认为尝试在子网上确定自己的主机名的整个想法可能并不那么有用,而是你必须将消息ping到另一台主机并查看它们所看到的IP地址。 (不幸的是在这种情况下没有意义,因为我不知道这个级别的程序中的其他同行。)例如,本地主机可能有多个NIC,因此有多个IP地址,所以试图确定单个主机 - 地址对是荒谬的。 (只有gethostbyname()
的正确分辨率并同时收听所有 gethostname()
结果吗?)
我还注意到,可以通过将名称传递到bind()
并设置addrinfo
标志来解析名称,这意味着getaddrinfo()
步骤可能是多余的。但是,我想这不是在这里完成的,因为他们试图确定主机名的某种无偏见的视图而不提供apriori。当然,它失败了,他们最终还是使用了AI_CANONNAME
!我也尝试向getnameinfo()
提供“localhost”,并在ai_canonname`下报告Linux下的主机名,但只是在OS X上导致“localhost”,所以不太有用,因为这应该是跨平台的
我想总结一下,我的问题是,在现代套接字编程中,为什么正确的方式(如果存在的话)可以获得可以通知子网对等的本地主机名?我倾向于仅仅返回gethostname()
的结果来替换此代码,但我想知道是否有更合适的解决方案使用现代调用,如getaddrinfo()
。
如果答案是没有办法做到这一点,我只需要使用gethostname()
,因为我必须在这里返回一些内容,否则会破坏API。
答案 0 :(得分:1)
我认为您应该查看有关IPv6编程的Ulrich Drepper's文章。它相对较短,可能会回答您的一些问题。我觉得它真的很有用。我发布此链接,因为如果没有(至少)伪代码,很难回答你的问题。
答案 1 :(得分:1)
如果我正确地读了这个,你只想获得一个非本地主机套接字地址,该地址可能会成功创建本地套接字,并且远程主机可以重新连接。
我有一个我写的函数,你可以引用名为“GetBestAddressForSocketBind”的函数。你可以从我的GitHub项目页面here上取下它。您可能需要引用父目录中的一些代码。
代码本质上只使用getifaddrs来枚举适配器并选择第一个“up”,而不是loopback / local并且具有所需地址系列的IP地址(AF_INET或AF_INET6)。
希望这有帮助。