在 Python 中将“little endian”十六进制字符串转换为 IP 地址

问题描述 投票:0回答:6

将这种形式的字符串转换为 IP 地址的最佳方法是什么:

"0200A8C0"
。字符串中存在的“八位字节”按相反顺序排列,即给定的示例字符串应生成
192.168.0.2

python sockets ip-address endianness
6个回答
35
投票

网络地址操作由套接字模块提供。

socket.inet_ntoa(packed_ip)

将 32 位打包 IPv4 地址(长度为四个字符的字符串)转换为其标准点分四组字符串表示形式(例如“123.45.67.89”)。当与使用标准 C 库并需要 struct in_addr 类型的对象的程序进行交互时,这非常有用,这是该函数作为参数的 32 位打包二进制数据的 C 类型。

您可以使用

packed ip
 将十六进制字符串转换为 
struct.pack()
以及小端、无符号长格式。

s = "0200A8C0"

import socket
import struct
addr_long = int(s, 16)
print(hex(addr_long))  # '0x200a8c0'
print(struct.pack("<L", addr_long))  # '\xc0\xa8\x00\x02'
print(socket.inet_ntoa(struct.pack("<L", addr_long)))  # '192.168.0.2'

8
投票
>>> s = "0200A8C0"
>>> bytes = ["".join(x) for x in zip(*[iter(s)]*2)]
>>> bytes
['02', '00', 'A8', 'C0']
>>> bytes = [int(x, 16) for x in bytes]
>>> bytes
[2, 0, 168, 192]
>>> print ".".join(str(x) for x in reversed(bytes))
192.168.0.2

简短明了;将其包装在一个带有错误检查的函数中以满足您的需求。


方便的分组功能:

def group(iterable, n=2, missing=None, longest=True):
  """Group from a single iterable into groups of n.

  Derived from http://bugs.python.org/issue1643
  """
  if n < 1:
    raise ValueError("invalid n")
  args = (iter(iterable),) * n
  if longest:
    return itertools.izip_longest(*args, fillvalue=missing)
  else:
    return itertools.izip(*args)

def group_some(iterable, n=2):
  """Group from a single iterable into groups of at most n."""
  if n < 1:
    raise ValueError("invalid n")
  iterable = iter(iterable)
  while True:
    L = list(itertools.islice(iterable, n))
    if L:
      yield L
    else:
      break

3
投票

你可以这样做:

>>> s = '0200A8C0'
>>> octets = [s[i:i+2] for i in range(0, len(s), 2)]
>>> ip = [int(i, 16) for i in reversed(octets)]
>>> ip_formatted = '.'.join(str(i) for i in ip)
>>> print ip_formatted
192.168.0.2

八位位组分割可能可以做得更优雅,但我想不出更简单的方法。

编辑: 或一行:

>>> s = '0200A8C0'
>>> print '.'.join(str(int(i, 16)) for i in reversed([s[i:i+2] for i in range(0, len(s), 2)]))
192.168.0.2

0
投票

我的尝试:

a = '0200A8C0'
indices = range(0, 8, 2)
data = [str(int(a[x:x+2], 16)) for x in indices]
'.'.join(reversed(data))

0
投票

您可以将十六进制转换为十进制 IP 的简单定义:

def hex2ip(iphex):
    ip = ["".join(x) for x in zip(*[iter(str(iphex))]*2)]
    ip = [int(x, 16) for x in ip]
    ip = ".".join(str(x) for x in (ip))
    return ip

# And to use it:
ip = "ac10fc40"
ip = hex2ip(iphex)
print(ip)

0
投票

在“现代”Python 中我这样做:

hex_ip_address = '0200A8C0'

'.'.join(str(octet) for octet in reversed(bytearray.fromhex(hex_ip_address)))

# or even shorter (maybe slower?)
".".join(map(str, reversed(bytearray.fromhex(hex_address))))

# gives '192.168.0.2'

步骤

  • builtin
    bytearray.fromhex 方法将
    4 byte hex
    地址字符串转换为
    4 integers
  • 列表
  • 列表在加入之前是
    reversed
    ,因为
    hex_ip_address
    采用 little-endian 表示法(最小地址处的最低有效字节)
  • 整数会转换为
    str
    ,以便可以与
    .
    字符连接
© www.soinside.com 2019 - 2024. All rights reserved.