How to create IPv6 socket at python? Why got the socket.error: (22, 'Invalid argument')?

后端 未结 2 1850
臣服心动
臣服心动 2021-01-11 18:00

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         


        
相关标签:
2条回答
  • 2021-01-11 18:15

    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
    17
    >>> sockaddr
    ('fe80::1%lo0', 50007, 0, 1)
    

    Second Issue

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

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

    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.

    0 讨论(0)
  • 2021-01-11 18:26

    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.

    0 讨论(0)
提交回复
热议问题