2010-10-27 8 views
6

Circa una settimana fa qualcuno su StackOverflow asked perché il loro codice Python per la connessione a un indirizzo IPv6 di collegamento locale non funzionava, e ho risposto che poiché era un indirizzo locale di collegamento, era necessario aggiungere un% en0 (o qualunque sia il nome dell'interfaccia locale desiderato) è suffisso al loro indirizzo IP di destinazione. Pensavo di sapere di cosa stavo parlando, quindi in realtà non ho testato il mio suggerimento prima di rispondere (vergognarmi!).Perché un suffisso% en0 non funziona per connettere un socket TCP IPv6 link-local in Python?

Oggi sono andato a usare la stessa tecnica per me stesso, solo per scoprire che non sembra funzionare. :^(Cioè, questo codice non funziona:

>>> 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 

Il codice seguente, d'altra parte, funziona (con o senza il suffisso en0%):

>>> from socket import * 
>>> s = socket(AF_INET6, SOCK_STREAM) 
>>> s.connect(('fe80::21f:5bff:fe3f:1b36%en0', 2001, 0, 6)) 
>>> 

... ma non mi piace farlo in questo modo, perché per capire quale ID dell'interfaccia ID fornire per l'ultimo argomento, devo eseguire un gruppo di codice non molto portatile per scorrere l'elenco delle interfacce locali, trovare l'interfaccia chiamata 'en0' ed estrae l'ID dell'ambito, che è un sovraccarico più complesso di quanto mi piacerebbe avere:

Dato che connect() sta accettando il suffisso% en0 all'indirizzo IP, perché non lo sta effettivamente utilizzando come previsto per determinare l'ID dell'ambito?

FWIW, sto testando con Python 2.6.1 sotto MacOS/X 10.6.4.

+0

In Windows, l'ID ambito della scheda NIC locale ha la precedenza su quello fornito nell'indirizzo di destinazione. :(Se non si associa prima intenzionalmente il socket, il sistema sceglie una NIC da utilizzare. L'id dell'obiettivo di destinazione è ** un ** suggerimento **. –

risposta

12

Questo è il modo corretto di fare una connessione 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() restituirà il corretto ambito numerico e il flusso di informazioni per voi.

Problemi correlati