首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何确保服务器在可能的情况下侦听IPv6,否则侦听IPv4?

如何确保服务器在可能的情况下侦听IPv6,否则侦听IPv4?
EN

Stack Overflow用户
提问于 2010-08-24 08:08:27
回答 2查看 2.6K关注 0票数 3

我正在尝试编写一个同时侦听IPv6和IPv4连接的服务器应用程序。实现这一点的正确方法似乎是侦听IPv6地址,该地址也将接受IPv4连接。

相关的代码片段是:

代码语言:javascript
复制
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's Guide复制过来的)

问题是,至少在我的系统上,getaddrinfo首先返回AF_INET,然后返回AF_INET6 --而根据规范,客户机的getaddrinfo首先返回AF_INET6。在我幼稚的方法中,服务器选择IPv4,客户端选择IPv6,连接失败。

我试图通过设置hints.ai_family = AF_INET6来解决这个问题,但在IPv6不可用的系统上失败了。

我看到了两个显而易见的解决方案:

a)尝试先请求IPv6,如果请求失败,则返回到IPv4,或者

b)遍历getaddrinfo的结果,查找IPv6,如果不存在,则选择第一个条目

但我不太喜欢其中任何一个;)我觉得应该有一种方法来说服getaddrinfo去做正确的事情,或者用一种不同的方法来实现我的目标。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-08-24 08:21:07

getaddrinfo()返回的地址顺序未指定,因此您必须准备好处理这两种情况。这可能意味着遍历列表,跟踪“目前为止最好的地址”。

或者,您可以尝试对getaddrinfo()返回的所有地址执行bind()listen()操作。这可能是最好的选择,因为某些OSes不接受到侦听0::0的IPv6套接字的IPv4连接。

票数 2
EN

Stack Overflow用户

发布于 2014-07-10 18:49:44

您的代码应该按照您所描述的方式工作。不幸的是,正如launchpad bug #673708中描述的那样,glibc中存在一个bug,这导致它首先选择IPv4。

计算机配置解决方案

在运行服务器程序的每台Linux计算机上都有一个变通方法:编辑/etc/gai.conf,启用所有默认规则(取消注释):

代码语言:javascript
复制
label ::1/128       0
label ::/0          1
label 2002::/16     2
label ::/96         3
label ::ffff:0:0/96 4
label fec0::/10     5
label fc00::/7      6
label 2001:0::/32   7

然后添加:

代码语言:javascript
复制
label ::ffff:7f00:1/128 8

然后,您的代码应该打开IPv6 (如果支持),并且还将接受IPv4连接。

代码解决方案

如果上述方法不实用(只有在您愿意更改运行的每台计算机上的配置时才实用),那么修改您的代码,使其更倾向于使用IPv6。例如,我做过这样的事情:

  • getaddrinfo()结果执行三次遍历。
  • 第一次遍历,首选IPv6。尝试清除IPV6_V6ONLY套接字选项以同时支持IPv6和IPv4。
  • 第二遍,首选IPv4。
  • 第三遍,采用任何可用的选项。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3552625

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档