c - 如何确保服务器在可能的情况下监听 IPv6 而在其他情况下监听 IPv4?

标签 c sockets networking ipv6 ipv4

我正在尝试编写一个服务器应用程序来监听 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/

相关文章:

java - 检查移动数据是否来自 sim one 或 sim 2 android

networking - 什么是谷歌云休息 API 中的网络 URI

java - Netty客户端有时收不到所有预期的消息

c++ - long long 和 long int 有什么区别

C fork 循环执行无限命令(事件文件上的 urandom/tail)

python - 为什么使用 python 从客户端接收图像后无法从服务器向客户端发送任何内容?

c++ - 如果 send() 返回 x 个字节,recv() 是否在一次调用中获得相同数量的字节?

Android 监听来自服务器套接字的消息

c - 流程创建和控制 - 同步

c - GCC 中的简单错误陷阱