8

大约一周前,StackOverflow 上的某个人为什么他们用于连接到 IPv6 本地链接地址的 Python 代码不起作用,我回答说因为它是本地链接地址,所以他们需要添加一个 %en0 (或任何所需的本地接口名称是)作为其目标 IP 地址的后缀。我以为我知道我在说什么,所以在回答之前我实际上并没有测试我的建议(我感到羞耻!)。

今天我为自己使用了相同的技术,却发现它似乎不起作用。:^( 也就是说,这段代码不起作用:

>>> from socket import *
>>> s = socket(AF_INET6, SOCK_STREAM)
>>> s.connect(('fe80::21f:5bff:fe3f:1b36%en0', 2001))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<string>", line 1, in connect
socket.error: [Errno 65] No route to host

另一方面,以下代码可以工作(有或没有 %en0 后缀):

>>> from socket import *
>>> s = socket(AF_INET6, SOCK_STREAM)
>>> s.connect(('fe80::21f:5bff:fe3f:1b36%en0', 2001, 0, 6))
>>> 

...但我不喜欢那样做,因为为了确定为最后一个参数提供哪个范围 ID 整数,我必须执行一堆不太便携的代码来迭代本地接口列出,找到名为“en0”的接口,并提取其范围 ID,这比我想要的复杂性开销更大。

鉴于 connect() 接受 IP 地址的 %en0 后缀,为什么它实际上没有按预期使用它来确定作用域 ID?

FWIW,我正在 MacOS/X 10.6.4 下使用 Python 2.6.1 进行测试。

4

1 回答 1

13

这是进行 ipv6 连接的正确方法:

>>> addrinfo = getaddrinfo('fe80::225:ff:fecd:5aa0%en0', 2001, AF_INET6, SOCK_STREAM)
>>> addrinfo
[(30, 1, 6, '', ('fe80::225:ff:fecd:5aa0%en0', 2001, 0, 4))]
>>> (family, socktype, proto, canonname, sockaddr) = addrinfo[0]
>>> s = socket(family, socktype, proto)
>>> s.connect(sockaddr)

getaddrinfo()将为您返回正确的数值范围和流量信息。

于 2010-10-27T06:33:45.700 回答