首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >getaddrinfo()在AI_PASSIVE中的使用

getaddrinfo()在AI_PASSIVE中的使用
EN

Stack Overflow用户
提问于 2011-11-13 18:49:23
回答 2查看 8.7K关注 0票数 6

getaddrinfo()函数不仅允许客户端程序高效地查找创建套接字到给定主机的正确数据,还允许服务器绑定到正确的套接字理论上。

我刚刚开始使用了解到的,并开始通过Python玩它:

代码语言:javascript
复制
from socket import *
for i in getaddrinfo(None, 22, AF_UNSPEC, SOCK_STREAM, IPPROTO_IP, AI_PASSIVE): i

收益率

代码语言:javascript
复制
(2, 1, 6, '', ('0.0.0.0', 22))
(10, 1, 6, '', ('::', 22, 0, 0))

是什么让我怀疑是不是出了什么问题。

我该怎么处理这些答案?我该不该

  • 对所有这些答案做一个listen()ing套接字,或者我应该
  • 选第一个真正管用的?

命令页中的示例建议我只使用第一个,如果它是无错误的,那么我会很高兴,但是之后我只能通过IPv4 n获得一个连接。

但是,如果我尝试所有这些方法,我必须使用两个服务器套接字,这是不必要的,因为如果满足某些条件(OS、套接字标志等),IPv6服务器套接字也会监听IPv4。

我哪里想错了?

编辑:显然,我没有想错,但我的电脑做了错误的事情。我使用随/etc/gai.conf附带的默认OpenSUSE。如果有人能给我指明正确的方向,那就太好了。

编辑2:在给定的情况下,strace在读取/etc/gai.conf (现在使用端口54321,因为我认为使用端口22可能会产生一些不好的影响,但情况并非如此)之后,会在内部进行以下调用:

代码语言:javascript
复制
socket(PF_INET6, SOCK_DGRAM, IPPROTO_IP) = 3
connect(3, {sa_family=AF_INET6, sin6_port=htons(54321), inet_pton(AF_INET6, "::", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, 28) = 0
getsockname(3, {sa_family=AF_INET6, sin6_port=htons(38289), inet_pton(AF_INET6, "::1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
connect(3, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 16) = 0
connect(3, {sa_family=AF_INET, sin_port=htons(54321), sin_addr=inet_addr("0.0.0.0")}, 16) = 0
getsockname(3, {sa_family=AF_INET6, sin6_port=htons(60866), inet_pton(AF_INET6, "::ffff:127.0.0.1", &sin6_addr), sin6_flowinfo=0, sin6_scope_id=0}, [28]) = 0
close(3)                                = 0

显然,这个决定是根据getsockname()调用的结果进行的.

顺便说一句:https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/673708和上面提到的其他bug报告证实了我的观察。有几个人声称新的行为是正确的,所以我显然坚持使用AF_INET6. :-(

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-11-13 19:47:29

您的getaddrinfo由于某种原因返回了错误的结果。它应该首先返回IPv6套接字。我唯一能想到的是,如果您的操作系统检测到您的系统有一个较低的prio IPv6 (6至4或Teredo),并避免它们,在这种情况下,IMO是错误的。编辑:刚刚注意到我自己的电脑做了同样的事情,我使用6到4。

但是,您可以两者都听,或者使用AF_INET6而不是AF_UNSPEC。然后可以执行setsockopt禁用IPV6_V6ONLY

getaddrinfo在这里做了一件合理的事情,并返回所有适用的结果(尽管我提到的顺序不对)。根据应用程序的不同,一个和两个侦听套接字都是有效的方法。

票数 3
EN

Stack Overflow用户

发布于 2011-11-13 23:05:59

JFTR:现在看来,在手册中给出的程序是错误的。

有两种可能的方法可以监听这两种IP类型:

  1. 只创建一个IPv6套接字并关闭v6唯一标志: 从套接字导入*s=套接字(AF_INET6,SOCK_STREAM) s.setsockopt(IPPROTO_IPV6,IPV6_V6ONLY,0) s.bind(.) resp. 从套接字导入* ai =getaddrinfo(无,.,AF_INET6,SOCK_STREAM,0,AI_PASSIVE) s= socket(ai,ai1,ai2) s.setsockopt(IPPROTO_IPV6,IPV6_V6ONLY,0) s.bind(ai4) 优点:
代码语言:javascript
复制
- simpler to handle

缺点:

代码语言:javascript
复制
- doesn't work under XP (AFAIK) - there are two different protocol stacks

  1. 使用两个套接字并打开v6only标志: 从套接字导入* aii =getaddrinfo(无,.,AF_UNSPEC,SOCK_STREAM,0,AI_PASSIVE) sl = [] for ai in aii: s= socket( ai,ai1,ai2)如果ai == AF_INET6: s.setsockopt(IPPROTO_IPV6,IPV6_V6ONLY,1) s.bind(ai4) sl.append(s) 并在接受循环中处理sl中的所有套接字(使用select()或非阻塞IO ) 优点:
代码语言:javascript
复制
- uses a (nearly) protocol independent handling with `getaddrinfo()`
- works under XP as well

缺点:

代码语言:javascript
复制
- complicated to handle

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8113805

复制
相关文章

相似问题

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