Почему суффикс%en0 не работает для подключения локального линк TCP-сокета IPv6 в Python?
Примерно неделю назад кто-то в Stackru спросил, почему его код Python для соединения с локальным адресом IPv6 не работает, и я ответил, что, поскольку это был локальный адрес канала, ему нужно добавить%en0 (или что-то в этом роде). желаемый local-interface-name is) суффикс к их целевому 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 ответ
Это правильный способ сделать соединение 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()
вернет вам правильный числовой объем и информацию о потоке.