The getaddrinfo()
理论上,该函数不仅允许客户端程序有效地找到正确的数据来创建给定主机的套接字,而且还允许服务器绑定到正确的套接字。
I just 了解到这一点并开始通过 Python 尝试它:
from socket import *
for i in getaddrinfo(None, 22, AF_UNSPEC, SOCK_STREAM, IPPROTO_IP, AI_PASSIVE): i
yields
(2, 1, 6, '', ('0.0.0.0', 22))
(10, 1, 6, '', ('::', 22, 0, 0))
是什么让我想知道是否出了什么问题。
我到底应该用这些答案做什么?我是不是该
- make a
listen()
荷兰国际集团所有这些答案的套接字,或者我应该
- 只选择第一个真正有效的吗?
中的示例manpage建议我只采用第一个,如果它没有错误就对它感到满意,但在我的示例中我只能通过 IPv4 获得连接。
但如果我尝试所有这些,我必须担心 2 个服务器套接字,这是不必要的,因为如果满足某些条件(操作系统、套接字标志等),IPv6 服务器套接字也会侦听 IPv4。
我哪里想错了?
编辑:显然,我没有想错,但我的电脑做了错误的事情。我使用默认的/etc/gai.conf
随 OpenSUSE 一起提供。如果有人能指出我正确的方向,那就太好了。
编辑2:在给定的情况下,strace
阅读后给出以下内部调用/etc/gai.conf
(现在使用端口54321,因为我认为使用端口22可能会产生一些不好的影响,但事实并非如此):
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()
打电话...
BTW: https://bugs.launchpad.net/ubuntu/+source/eglibc/+bug/673708那里提到的其他错误报告证实了我的观察。那里有几个人声称新行为是正确的,所以我显然坚持使用AF_INET6
... :-(