某些操作系统似乎不支持双堆栈套接字。我正在寻找一种可靠的方法来检测是否支持此功能。我当前的建议(尚未测试)是在我尝试将套接字置于双堆栈模式时检查setsockopt的返回值以关闭IPV6_V6ONLY。您认为这有效还是有更好的解决方案?
由于
答案 0 :(得分:1)
我想到的一种方法是尝试创建仅支持IPv6的UDP套接字并将其连接到IPv4映射地址。这不会产生任何实际的网络流量,但通过查看代码的行为和分配给套接字的结果本地地址,您可以确定套接字是否实际上是仅IPv6。
这是演示这个想法的Python代码。这可以直接映射到执行相同系统调用序列的等效C代码:
import socket
s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM, 0)
s.setsockopt(socket.IPPROTO_IPV6, socket.IPV6_V6ONLY, 1)
s.connect(('::ffff:169.254.1.1', 53))
print s.getsockname()
可能的结果:
setsockopt
选项不受支持,IPV6_V6ONLY
失败。connect
由于套接字仅为IPv6而失败,并且连接时认识到您不允许将此类套接字绑定到IPv4映射地址。connect
失败,没有主机路由。如果遇到这种情况,你就处于黑暗中,因为你不知道它是在寻找IPv4路由还是IPv6路由,你必须尝试连接到其他地址才能找出哪个是情况下。getsockname
返回IPv4映射地址,表示IPV6_V6ONLY
且套接字不是仅IPv6。getsockname
返回IPv4地址以外的IPv6地址,这意味着套接字是仅IPv6的,并且连接使用的代码路径不知道IPv4映射地址在某种程度上是特殊的。我认为无法预测您在各种操作系统上会遇到什么怪癖。但我相信我建议的套接字API调用序列会揭示任何这样的怪癖。因此,您必须在与您相关的目标操作系统上进行测试,以了解它们各自的行为方式,并且可能会产生简化版本的测试就足够了。