Take the 2-minute tour ×

I want to ceate Ipv6 socket at python, I do it like this:

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

But it failed:

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

Can anyone help me? thanks!

I redo it like this, but still cannot work

    >>>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)
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "<string>", line 1, in bind
socket.error: (22, 'Invalid argument')
share|improve this question
Did you verify socket.has_ipv6 returns true? –  Daniel Goldberg Sep 27 '10 at 7:17
Why are you binding to an arbitrary link-local address? In 99% of cases, you want to bind to :: (i.e. all interfaces). –  Jeremy Visser Sep 27 '10 at 14:16

2 Answers 2

up vote 4 down vote accepted

There are two parts to the problem

First Issue

You should use the sa.bind(sockaddr) where sockaddr is obtained from 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
>>> sockaddr
('fe80::1%lo0', 50007, 0, 1)

Second Issue

If you look at the example provided in the socket documentation at

Socket accepts three arguments

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

As per the documentation

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.

And if you used getaddressinfo to get the values for proto then the value is different from the default 0

But when I executed the following, I get a different protocol value - 17. You may want to investigate this too.

And of course socket.has_ipv6 is True for me.

share|improve this answer
no, it still cannot work –  Jianzhong Oct 8 '10 at 9:20
I have edited my question using your method, which include the error.thanks >>> socket.has_ipv6 True –  Jianzhong Oct 9 '10 at 2:03

The other thing missing from the above is that fe80::* are link-local addresses.As such you can't technically use them without a Scope ID.
Just in case that didn't sink in, "link-local" means that the address can only be used on a specific link, but the corollary is that since the address is link-specific theoretically you could have that same address on more than one link.
Now granted that in most cases a link-local address is generated from the already unique hardware (EUI-48) address by converting it to an EUI-64 and then flipping on the U/L bit (see) but this is not the only way you can generate a link-local address and other mechanisms could result in re-using the address (I don't think there's anything that prohibits this). So now you know why it didn't work.
The next question is how do you fix it, or rather where do you get the Scope ID. This is unfortunately non-obvious. If you read the IPV6 RFCs that discuss "Scope" you find that it is defined in a general fashion. In practice if you are running this code in Linux (maybe also Windows/Mac?) you can use the interface index.

Note that there's currently a bug in nss-mdns such that .local names are returned with scope id always zero so in Linux using .local names basically doesn't work unless your code has already figured out the scope id and sets it by itself.

share|improve this answer

Your Answer


