我正在为P2P应用程序编写一个客户端,协议的规范说每个数据包的标头应该具有特定字节长度的每个字段,如下所示:
Version: 1 Byte
Type: 1 Byte
Length: 2 Bytes
And then the data
我已经有了打包和解包标题字段的方法(我认为)像这样:
packed = struct.pack('cch' , '1' , '1' , 26)
这为数据长度为26的数据包构建了一个标头,但是当解包数据时,我不确定如何在之后获取其余数据。要打开包装,我们需要知道所有字段的大小,除非我遗漏了什么?我想打包数据我会使用格式指示符'cch26s'的含义:
1 Byte char
1 Byte char
2 Byte short
26 Byte char array
但是,当我不知道数据包中将包含多少数据时,如何解压缩数据呢?
答案 0 :(得分:3)
您描述协议的方式,您应首先解包前四个字节,然后提取长度(16位int)。这告诉你在第二步中要解包的字节数。
version, type, length = struct.unpack("cch", packed[:4])
content, = struct.unpack("%ds" % length, packed[4:])
如果一切都结束了。 unpack()要求打包缓冲区包含与解压缩数据完全相同的数据。另外,检查长度计数中是否包含4个头字节。
答案 1 :(得分:2)
您可以通过检查len(data)
来猜测要解包的字符数。
这是一个帮助你的函数:
def unpack(fmt, astr):
"""
Return struct.unpack(fmt, astr) with the optional single * in fmt replaced with
the appropriate number, given the length of astr.
"""
# http://stackoverflow.com/a/7867892/190597
try:
return struct.unpack(fmt, astr)
except struct.error:
flen = struct.calcsize(fmt.replace('*', ''))
alen = len(astr)
idx = fmt.find('*')
before_char = fmt[idx-1]
n = (alen-flen)/struct.calcsize(before_char)+1
fmt = ''.join((fmt[:idx-1], str(n), before_char, fmt[idx+1:]))
return struct.unpack(fmt, astr)
你可以像这样使用它:
unpack('cchs*', data)