我试图在 Python 2.7 中从 /proc/net/tcp6
读取 IPv6 地址。以下是 /proc/net/tcp6
中使用的 IPv6 表示示例:
00000000000000000000000000000000
00000000000000000000000001000000
0000000000000000FFFF00001F00C80A
我遇到的问题是将它们转换为“正确的”IPv6 表示形式,如维基百科所述:
An IPv6 address is represented as eight groups of four hexadecimal digits, each group representing 16 bits (two octets). The groups are separated by colons (:). An example of an IPv6 address is:
2001:0db8:85a3:0000:0000:8a2e:0370:7334
[...] the example address can be further simplified:
2001:db8:85a3::8a2e:370:7334
这似乎可以在 socket.inet_ntop
的帮助下最轻松地完成和 struct.pack
.
但是我不知 Prop 体要采取哪些步骤来生成这两个函数所需的特定格式。
使用 Python 2.7 stdlib 中的其他东西的任何其他方法当然同样受欢迎。
只是为了比较,下面是我现在如何处理从 /proc/net/tcp
读取的 IPv4 地址:
>>> addr = '0101007F'
>>> addr = int(addr, 16)
>>> addr = struct.pack('<I', addr)
>>> addr = socket.inet_ntoa(addr)
>>> print addr
127.0.1.1
很遗憾,inet_ntoa
不支持 IPv6 地址,您必须改用 inet_ntop(AF_INET6, packed_ipv6)
。
但是我不知道如何使用 struct.pack
函数将上面的那些字符串转换为 in6_addr
结构。
最佳答案
这是一种有效的方法,可以自动处理原生字节顺序:
def ipv6(addr):
addr = addr.decode('hex')
addr = struct.unpack('>IIII', addr)
addr = struct.pack('@IIII', *addr)
addr = socket.inet_ntop(socket.AF_INET6, addr)
return addr
示例:
>>> ipv6('00000000000000000000000001000000')
'::1'
>>> ipv6('B80D01200000000067452301EFCDAB89')
'2001:db8::123:4567:89ab:cdef'
步骤:
- 地址转字节串(
decode('hex')
), - 分成4个片,保持字节顺序不变(
>IIII
), - 重新打包,将每个切片转换为 native 字节顺序 (
@IIII
), - 传递给
socket.inet_ntop
,最终生成正确的 IPv6 表示
在 systems that use little endian 上,字节串将从 DCBA-HGFE-LKJI-PONM
转换为 ABCD-EFGH-IJKL-MNOP
。参见 struct
模块的 byte order notation 。
unpack
和 pack
部分的替代方案,但在我的系统上速度是原来的两倍,而且它不会自动处理 native 字节顺序(这里假定为小字节序) :
addr = ''.join(addr[i:i+4][::-1] for i in range(0, 16, 4))
关于python - 从/proc/net/tcp6 解析 IPv6 地址(python 2.7),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41940483/