Почему суффикс% en0 не работает для подключения локального линк TCP-сокета IPv6 в Python? - PullRequest
7 голосов
/ 27 октября 2010

Неделю назад или около того кто-то в StackOverflow спросил , почему их код Python для соединения с локальным адресом IPv6 не работает, и я ответил, что, поскольку это был локальный адрес, который им нужен добавить суффикс% 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))
>>> 

... но мне не нравится делать это таким образом, потому что, чтобы выяснить, какое целое число идентификатора области действия нужно предоставить для последнего аргумента, я должен выполнить кучу не очень переносимого кода для итерации список локальных интерфейсов, найдите интерфейс с именем 'en0' и извлеките его идентификатор области видимости, что требует больше сложностей, чем хотелось бы.

Учитывая, что connect () принимает суффикс% en0 к IP-адресу, почему он фактически не использует его, как ожидается, для определения идентификатора области?

FWIW, я тестирую с Python 2.6.1 под MacOS / X 10.6.4.

1 Ответ

13 голосов
/ 27 октября 2010

Это правильный способ подключения 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() вернет вам правильный числовой объем и информацию о потоке.

...