如何解压 python 结构中的可变长度数据
How to unpack variable length data in python struct
我正在构建一个 p2p 应用程序,我需要在其中解压来自跟踪器的 udp 通告响应。
announce response:
Offset Size Name
0 32-bit integer action
4 32-bit integer transaction_id
8 32-bit integer interval
12 32-bit integer leechers
16 32-bit integer seeders
20 + 6 * n 32-bit integer IP address
24 + 6 * n 16-bit integer TCP port
20 + 6 * N
我需要从上面table读取名称字段中列出的所有数据,但播种机、IP地址和端口的值是可变的。
如何使用 python 结构从响应中正确解压所有数据?
struct
模块对于解包二进制数据非常有用。
action, transaction_id, interval, leechers, seeders = struct.unpack('>iiiii', announse_response)
然后您必须遍历其余数据以获取所有 ip/port 数据:
ip_port_list = []
while True:
try: ip_port_list.append(struct.unpack('>ih', announse_response))
except: break
没有struct就得一个字节一个字节的读,然后转换big endian的问题。
我经历过同样的挣扎,所以为此写了一个简单的包 binread。
from binread import formatclass, U32, U16, Array
@formatclass
class Seeder:
ip_addr = U32
tcp_port = U16
@formatclass
class AnnounceResponse:
action = U32
transaction_id = U32
interval = U32
leechers = U32
seeders = U32
# `length` refers to the value of the previous `seeders` field
seeder_data = Array(Seeder, length="seeders")
# `data` is a bytes object
resp = AnnounceResponse.read(data)
print(resp.transaction_id)
print(len(resp.seeder_data))
print(resp.seeder_data[0].tcp_port)
您可以选择使用 @formatclass(byteorder='little')
(或 'big'
)为所有值指定字节序。
完全公开,我是 binread 的作者。
我正在构建一个 p2p 应用程序,我需要在其中解压来自跟踪器的 udp 通告响应。
announce response:
Offset Size Name
0 32-bit integer action
4 32-bit integer transaction_id
8 32-bit integer interval
12 32-bit integer leechers
16 32-bit integer seeders
20 + 6 * n 32-bit integer IP address
24 + 6 * n 16-bit integer TCP port
20 + 6 * N
我需要从上面table读取名称字段中列出的所有数据,但播种机、IP地址和端口的值是可变的。
如何使用 python 结构从响应中正确解压所有数据?
struct
模块对于解包二进制数据非常有用。
action, transaction_id, interval, leechers, seeders = struct.unpack('>iiiii', announse_response)
然后您必须遍历其余数据以获取所有 ip/port 数据:
ip_port_list = []
while True:
try: ip_port_list.append(struct.unpack('>ih', announse_response))
except: break
没有struct就得一个字节一个字节的读,然后转换big endian的问题。
我经历过同样的挣扎,所以为此写了一个简单的包 binread。
from binread import formatclass, U32, U16, Array
@formatclass
class Seeder:
ip_addr = U32
tcp_port = U16
@formatclass
class AnnounceResponse:
action = U32
transaction_id = U32
interval = U32
leechers = U32
seeders = U32
# `length` refers to the value of the previous `seeders` field
seeder_data = Array(Seeder, length="seeders")
# `data` is a bytes object
resp = AnnounceResponse.read(data)
print(resp.transaction_id)
print(len(resp.seeder_data))
print(resp.seeder_data[0].tcp_port)
您可以选择使用 @formatclass(byteorder='little')
(或 'big'
)为所有值指定字节序。
完全公开,我是 binread 的作者。