import struct
port = 1331
fragments = [1,2,3,4]
flags = bytes([64])
name = "Hello World"
data = struct.pack('HcHH', port, flags, len(fragments), len(name))
print(int.from_bytes(data[3:5], byteorder='big'))
print(int.from_bytes(data[5:7], byteorder='big'))
print(int.from_bytes(data[0:2], byteorder='little'))
当我像这样打印它们时,它们会正确地出来。似乎端口使用小尾数,而len(fragments)
和len(name)
使用大尾数。如果我还在端口上进行大端字节排序,则它将得到错误的值。
那么为什么结构会如此表现?还是我错过了什么?
>>> struct.calcsize('HcHH')
8
>>> struct.calcsize('HHHc')
7
因此您的数据与您所想的不一致。正确的拆包是:
print(int.from_bytes(data[4:6], byteorder='little'))
# 4
print(int.from_bytes(data[6:], byteorder='little'))
# 11
事实证明,偶然地,'c'的添加字节为'\ x00',并使您的字节链在big-endian中正确:
>>> data
b'3\x05@\x00\x04\x00\x0b\x00'
^^^^
this is the intruder
pack
结果看起来像这样(打印有struct.pack('@HcHH', port, flags, len(fragments), len(name))
:
'.'.join(f'{x:02X} for x in data')
数字4用小尾数编码在字节4和5中,而11编码在字节6和7中。字节3是一个填充字节,由33.05.40.00.04.00.0B.00
0 1 2 3 4 5 6 7
插入以适当地将后面的pack
对齐到均匀边界。
每short
:注默认情况下,打包给定C结构的结果包括填充字节,以维护所涉及C类型的正确对齐;同样,拆箱时也要考虑对齐方式。选择此行为是为了使打包结构的字节与对应的C结构的内存中的布局完全对应。要处理平台无关的数据格式或忽略隐式填充字节,请使用docs大小和对齐方式,而不是standard
大小和对齐方式:有关详细信息,请参见native
。要删除对齐字节并证明您对字节位置的假设,同时保持本机字节顺序,请使用
Byte Order, Size, and Alignment
您还可以通过使用struct.pack('=HcHH', port, flags, len(fragments), len(name))
或<
作为前缀来使用固定字节顺序。