我正在尝试编写一个服务器应用程序来监听 IPv6 和 IPv4 连接。完成此任务的正确方法似乎是监听 IPv6 地址,它也将接受 IPv4 连接。
相关代码是:
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;
getaddrinfo(NULL, MYPORT, &hints, &res);
(几乎是从 Beej 的指南中复制粘贴的)
问题是,至少在我的系统上,getaddrinfo
返回的条目首先是 AF_INET
,然后是 AF_INET6
-- 而客户端的 getaddrinfo
根据规范首先返回 AF_INET6
。使用我天真的方法,服务器选择 IPv4,客户端选择 IPv6 并且连接失败。
我试图通过设置 hints.ai_family = AF_INET6
来解决这个问题,但是在 IPv6 不可用的系统上失败了。
我看到两个明显的解决方案:
a) 首先尝试请求 IPv6,如果失败则回退到 IPv4,或者
b) 遍历 getaddrinfo
的结果,查找 IPv6,如果不存在,则选择第一个条目
但我不太喜欢其中任何一个 ;) 我觉得应该有一种方法可以说服 getaddrinfo
做正确的事情,或者可能是一种不同的方法来实现我的目标。
最佳答案
getaddrinfo()
返回的地址顺序是未指定的,因此您必须准备好处理这两种情况。这可能意味着遍历列表,跟踪“迄今为止看到的最佳地址”。
或者,您可以尝试bind()
和listen()
所有 getaddrinfo()< 返回的地址
。这可能是最佳选择,因为某些操作系统不接受 IPv4 连接到监听 0::0
的 IPv6 套接字。
关于c - 如何确保服务器在可能的情况下监听 IPv6 而在其他情况下监听 IPv4?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3552625/