【问题标题】:Converting IPv4 Address to a Hex IPv6 Address in Python在 Python 中将 IPv4 地址转换为十六进制 IPv6 地址
【发布时间】:2013-11-14 01:55:46
【问题描述】:

问:编写一个程序,提示用户输入 IP 地址,然后将其转换为以 10 为底的二进制和十六进制值。然后程序将十六进制值转换为 RFC3056 IPv6 6to4 地址。

我的基数为 10 和二进制部分可以工作,但我似乎无法理解十六进制部分。格式字符串方法可以以某种方式用于完成同样的事情吗?或者在这种情况下我需要导入 ipaddress 模块吗?

#!/usr/bin/python3

ip_address = input("Please enter a dot decimal IP Address: ")

"""This part converts to base 10"""
ListA = ip_address.split(".")
ListA = list(map(int, ListA))
ListA = ListA[0]*(256**3) + ListA[1]*(256**2) + ListA[2]*(256**1) + ListA[3]
print("The IP Address in base 10 is: " , ListA)

"""This part converts to base 2"""
base2 = [format(int(x), '08b') for x in ip_address.split('.')]
print("The IP Address in base 2 is: ", base2)

"""This part converts to hex"""
hexIP = []
[hexIP.append(hex(int(x))[2:].zfill(2)) for x in ip_address.split('.')]
hexIP = "".join(hexIP)
print("The IP Address in hex is: " , hexIP)

编辑:设法将 IP 地址转换为十六进制值。现在如何将此十六进制值转换为 IPv6 地址?

【问题讨论】:

    标签: python hex type-conversion ip-address ipv6


    【解决方案1】:
    >>> ip_address = '123.45.67.89'
    >>> numbers = list(map(int, ip_address.split('.')))
    >>> '2002:{:02x}{:02x}:{:02x}{:02x}::'.format(*numbers)
    '2002:7b2d:4359::'
    

    【讨论】:

    • 完美!非常感谢:)
    • 6to4 address 必须以 '2002::/16' 开头,即在您的示例中为 '2002:7b2d:4359::'
    • 改成:'2002:0:0:0:0:ffff:{:02x}{:02x}:{:02x}{:02x}'.format(*numbers)
    • 不考虑子网,但现在可以。
    • @user1819786: 0:0:0:0:ffff: 在这种情况下也不正确。点击我之前评论中的两个链接。
    【解决方案2】:

    在 Python 3.3 中,您可以使用 ipaddress module 来操作 IPv4、IPv6 地址:

    #!/usr/bin/env python3
    import ipaddress
    
    # get ip address 
    while True:
        ip4str = input("Enter IPv4 (e.g., 9.254.253.252):")
        try:
            ip4 = ipaddress.IPv4Address(ip4str)
        except ValueError:
            print("invalid ip address. Try, again")
        else:
            break # got ip address
    
    # convert ip4 to rfc 3056 IPv6 6to4 address
    # http://tools.ietf.org/html/rfc3056#section-2
    prefix6to4 = int(ipaddress.IPv6Address("2002::"))
    ip6 = ipaddress.IPv6Address(prefix6to4 | (int(ip4) << 80))
    print(ip6)
    assert ip6.sixtofour == ip4
    
    # convert ip4 to a base 10
    print(int(ip4))
    # convert ip4 to binary (0b)
    print(bin(int(ip4)))
    # convert ip4 to hex (0x)
    print(hex(int(ip4)))
    

    【讨论】:

      【解决方案3】:

      如果您只想在 IPv6 上下文中使用 IPv4 地址(例如,通过传递给使用socket.AF_INET6 地址系列创建的socket.connect()),您可以使用RFC4291, Section 2.2 中描述的语法:

      >>> import socket
      >>> a = '10.20.30.40'
      >>> s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM)
      >>> s.connect(('2002::' + a, 9))
      

      即只需将::ffff: 添加到 IPv4 地址,您就会得到一个有效的 6to4 地址。如果您想将此地址转换为更常见的十六进制形式,我建议使用您提到的标准库ipaddress 模块:

      >>> import ipaddress
      >>> a = '10.20.30.40'
      >>> print(ipaddress.IPv6Address('2002::' + a).compressed)
      '2002::a14:1e28'
      

      【讨论】:

        【解决方案4】:

        在参考解决方案之前,请查看this doc,了解 ipv6 表示的转换和约定。

        def ipconversion4to6(ipv4_address):
            hex_number = ["{:02x}".format(int(_)) for _ in address.split(".")]
            ipv4 = "".join(hex_number)
            ipv6 = "2002:"+ipv4[:4]+":"+ipv4[4:]+"::"
            return ipv6
        

        【讨论】: