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

Я хочу создать сокет 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')

Ответы [ 2 ]

5 голосов
/ 27 сентября 2010

Проблема состоит из двух частей

Первый выпуск

Вам следует использовать 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)

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

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

Socket принимает три аргумента

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 для меня верно.

3 голосов
/ 03 января 2013

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...