Как создать сокет IPv6 на python? Почему получен сокет socket.error: (22, «Неверный аргумент»)?

Я хочу установить сокет Ipv6 на Python, я делаю это так:

#!/usr/bin/env python
import sys
import struct
import socket

host = 'fe80::225:b3ff:fe26:576'
sa = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
sa.bind((host , 50000))

Но это не удалось

socket.error: (22, 'Invalid argument') ?

Может кто-нибудь мне помочь? Спасибо!

Я повторяю это так, но все еще не могу работать

    >>>host = 'fe80::225:b3ff:fe26:576'
    >>>sa = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
    >>>res = socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_DGRAM, 0, socket.AI_PASSIVE)
    >>>family, socktype, proto, canonname, sockaddr = res[0]
    >>>print sockaddr
('fe80::225:b3ff:fe26:576', 50001, 0, 0)
    >>>sa.bind(sockaddr)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<string>", line 1, in bind
socket.error: (22, 'Invalid argument')
 Jeremy Visser27 сент. 2010 г., 16:16
Почему вы привязываетесь к произвольному локальному адресу? В 99% случаев вы хотите привязать к :: (то есть ко всем интерфейсам).
 Daniel Goldberg27 сент. 2010 г., 09:17
Вы проверяли, что socket.has_ipv6 возвращает true?

Ответы на вопрос(2)

Решение Вопроса

Есть две части проблемы

Первая проблема

Вы должны использовать sa.bind (sockaddr), где sockaddr получен из getaddrinfo

>>> HOST = 'localhost'
>>> PORT = 50007 
>>> res = socket.getaddrinfo(HOST, PORT, socket.AF_UNSPEC, socket.SOCK_DGRAM, 0, socket.AI_PASSIVE)
>>> family, socktype, proto, canonname, sockaddr = res[1]
>>> proto
17
>>> sockaddr
('fe80::1%lo0', 50007, 0, 1)

Второй выпуск

Если вы посмотрите на пример, приведенный в документации по сокету,

http://docs.python.org/release/2.5.2/lib/module-socket.html

Сокет принимает три аргумента

socket( [family[, type[, proto]]])

Согласно документации

Create a new socket using the given address family, 
socket type and protocol number. The address family 
should be AF_INET (the default), AF_INET6 or AF_UNIX. 
The socket type should be SOCK_STREAM (the default), 
SOCK_DGRAM or perhaps one of the other "SOCK_" constants. 
The protocol number is usually zero and may be omitted in that case.

И если вы использовали getaddressinfo для получения значений для proto, то значение отличается от значения по умолчанию 0

Но когда я выполнил следующее, я получил другое значение протокола - 17. Возможно, вы тоже захотите исследовать это.

И, конечно, socket.has_ipv6 - это правда для меня.

 Jianzhong08 окт. 2010 г., 11:20
нет, это все еще не может работать
 Jianzhong09 окт. 2010 г., 04:03
Я отредактировал свой вопрос, используя ваш метод, который включает error.thanks >>> socket.has_ipv6 True

Еще одна вещь, отсутствующая в приведенном выше, это то, что fe80 :: * являются локальными адресами ссылок. Таким образом, вы не можете технически использовать их без идентификатора области.
На всякий случай, если бы не утонулlink-local«означает, что адрес может использоваться только для конкретной ссылки, но следствие заключается в том, что, поскольку адрес теоретически зависит от конкретной ссылки, вы можете иметь один и тот же адрес более чем на одной ссылке.
Теперь предоставлено, что в большинстве случаев локальный адрес ссылки генерируется из ужеуникальный аппаратный (EUI-48) адрес преобразовав его в EUI-64, а затем переключив бит U / L (увидеть) но это не единственный способ создания локального адреса ссылки, и другие механизмы могут привести к повторному использованию адреса (я не думаю, что есть что-то, что запрещает это). Итак, теперь вы знаете, почему это не сработало.
Следующий вопрос, как вы это исправите, или жескорее, где вы получаете Scope ID. Это, к сожалению, неочевидно. Если вы читаете RFC IPV6, которые обсуждают "Scope"вы обнаружите, что он определен в общем виде. На практике, если вы запускаете этот код в Linux (возможно, также в Windows / Mac?), вы можете использовать индекс интерфейса.

Обратите внимание, что в настоящее время в nss-mdns есть ошибка, заключающаяся в том, что имена .local возвращаются с идентификатором области всегда равным нулю, поэтому в Linux использование имен .local в основном не работает, если ваш код уже не определил идентификатор области и не установил его сам.

Ваш ответ на вопрос