2010-09-27 10 views
9

Voglio ceate presa Ipv6 in pitone, lo faccio in questo modo:Come creare un socket IPv6 su python? Perché ho preso il socket.error: (22, 'argomento non valido')?

#!/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)) 

Ma non è riuscito:

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

Qualcuno mi può aiutare? Grazie!

ho rifare come questo, ma ancora non in grado di lavorare

>>>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') 
+0

Hai verificato che socket.has_ipv6 restituisce true? –

+0

Perché si sta vincolando a un indirizzo locale di collegamento arbitrario? Nel 99% dei casi, si desidera eseguire il binding a :: (ad esempio tutte le interfacce). –

risposta

5

Ci sono due parti al problema

Prima emissione

Si dovrebbe usare il sa.bind (sockaddr) dove sockaddr è ottenuto da 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) 

Seconda Edizione

Se guardate l'esempio fornito nella documentazione presa in

Socket accetta tre argomenti

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

Come per la documentazione

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. 

E se è stato utilizzato getaddressinfo per ottenere i valori per proto allora il valore è diverso da quello predefinito 0

Ma quando ho eseguito il seguente, ottengo un valore diverso protocollo - 17. Si consiglia per indagare anche su questo.

E ovviamente socket.has_ipv6 è vero per me.

+0

no, non può ancora funzionare – Jianzhong

+0

Ho modificato la mia domanda usando il tuo metodo, che include l'errore.thanks >>> socket.has_ipv6 True – Jianzhong

3

L'altra cosa che manca da quanto sopra è che fe80 :: * sono indirizzi locali di collegamento. Come tali non è possibile utilizzarli tecnicamente senza un ID ambito.
Nel caso in cui non è stato eseguito il sinking, "link-local" significa che l'indirizzo può essere utilizzato solo su un collegamento specifico, ma il corollario è che poiché l'indirizzo è specifico del collegamento teoricamente si potrebbe avere lo stesso indirizzo su più di uno collegamento.
Ora concesso che nella maggior parte dei casi viene generato un indirizzo locale di collegamento dall'indirizzo univoco (EUI-48) convertendolo in un EUI-64 e quindi ruotando sul bit U/L (see) ma questo è non l'unico modo in cui è possibile generare un indirizzo locale di collegamento e altri meccanismi potrebbe comportare il riutilizzo dell'indirizzo (non credo che ci sia qualcosa che vieta questo). Quindi ora sai perché non ha funzionato.
La prossima domanda è come si risolve il problema o piuttosto dove si ottiene l'ID ambito. Questo purtroppo non è ovvio. Se leggi gli RFC IPV6 che trattano "Scope", scopri che è definito in modo generale. In pratica se usi questo codice in Linux (forse anche Windows/Mac?) Puoi usare l'indice dell'interfaccia.

Nota che c'è attualmente un bug nel NSS-mdns tale che i nomi .local vengono restituiti con portata id azzerare sempre così in Linux utilizzando i nomi .local fondamentalmente non funziona a meno che il codice ha già capito l'id portata e set da solo

Problemi correlati