unpack_from nécessite une zone tampon d'au moins 4 octets

Je suis de la réception d'un paquet de client, composé de plusieurs champs. J'ai lu tous les champs correctement, mais quand il s'agit de la dernière champ qui est tag_end, python me donne une erreur:

unpack_from nécessite une zone tampon d'au moins 4 octets non trouvé.

c'est le code:

def set_bin(self, buf):
"""Reads a vector of bytes (probably received from network or
read from file) and tries to construct the packet structure
from it, by reading each packet member from the buffer.  This
is somehow like deserializing the packet.
"""
assert isinstance(buf, bytearray), 'buffer type is not valid'
offset = 0
print("$$$$$$$$$$$$$$$$ set bin $$$$$$$$$$$$$$$$$")
try:
(self._tag_start, self._version, self._checksum, self._connection_id,
self._packet_seq) = Packet.PACKER_1.unpack_from(str(buf), offset)
except struct.error as e:
print(e)
raise DeserializeError(e)
except ValueError as e:
print(e)
raise DeserializeError(e)
#I=4 H=2 B=1
offset = Packet.OFFSET_GUID     #14 correct
self._guid = buf[offset:offset+Packet.UUID_SIZE] #14-16 correct
offset = Packet.OFFSET_GUID + Packet.UUID_SIZE
print("$$$$$$$$$$$$$$$$ GUID read successfully  $$$$$$$$$$$$$$$$$")
try:
(self._timestamp_sec, self._timestamp_microsec, self._command,
self._command_seq, self._subcommand, self._data_seq,
self._data_length) = Packet.PACKER_3.unpack_from(str(buf), offset)
except struct.error as e:
print(e)
raise DeserializeError(e)
except ValueError as e:
print(e)
raise DeserializeError(e)
print("$$$$$$$$$$$$$$$$ timestamps read successfully $$$$$$$$$$$$$$$$$")
offset = Packet.OFFSET_AUTHENTICATE
self._username = buf[offset:offset + self.USERNAME_SIZE]        #Saman
offset += self.USERNAME_SIZE
print("$$$$$$$$$$$$$$$$ username read successfully  $$$$$$$$$$$$$$$$$")
self._password = buf[offset:offset+self.USERNAME_SIZE]
offset += self.PASSWORD_SIZE
print("$$$$$$$$$$$$$$$$ password read successfully $$$$$$$$$$$$$$$$$")
self._data = buf[offset:offset+self._data_length]
offset = offset + self._data_length
print("$$$$$$$$$$$$$$$$ data read successfully  $$$$$$$$$$$$$$$$$")
try:
(self._tag_end,) = Packet.PACKER_4.unpack_from(str(buf), offset)
except struct.error as e:
print(e)
raise DeserializeError(e)
except ValueError as e:
print(e)
raise DeserializeError(e)
print("$$$$$$$$$$$$$$$$ tag end read successfully $$$$$$$$$$$$$$$$$")
if len(buf) != Packet.PACKER.size + self._data_length:
print('failed to deserialize binary data correctly and construct the packet due to extra data')
else:
print('@@@@@@@@@@@@@@@ Deserialized Successfully')

et c'est une des constantes utilisées dans le code:

STRUCT_FORMAT_STR   = r'=IHIHH 16B IIHHHHH I 6c 9c' #Saman
STRUCT_FORMAT_STR_1 = r'=IHIHH'
STRUCT_FORMAT_STR_2 = r'=16B'
STRUCT_FORMAT_STR_3 = r'=IIHHHHH'
STRUCT_FORMAT_STR_4 = r'=I'
STRUCT_FORMAT_STR_5 = r'=6c'
STRUCT_FORMAT_STR_6 = r'=9c'
UUID_SIZE   = 16
OFFSET_GUID = 14
#OFFSET_DATA = 48     #shifting offset data by 15 char      
OFFSET_AUTHENTICATE = 48
PACKER   = struct.Struct(str(STRUCT_FORMAT_STR))     #Saman
PACKER_1 = struct.Struct(str(STRUCT_FORMAT_STR_1))
PACKER_2 = struct.Struct(str(STRUCT_FORMAT_STR_2))
PACKER_3 = struct.Struct(str(STRUCT_FORMAT_STR_3))
PACKER_4 = struct.Struct(str(STRUCT_FORMAT_STR_4))
PACKER_5 = struct.Struct(str(STRUCT_FORMAT_STR_5))
PACKER_6 = struct.Struct(str(STRUCT_FORMAT_STR_6))
BYTES_TAG_START = PACKER_4.pack(TAG_START)
BYTES_TAG_END   = PACKER_4.pack(TAG_END)

et l'initialisation du paquet d'objet, où il initialise les champs:

def init(self, **kwargs):
si 'buf' dans kwargs:
auto.set_bin(kwargs['buf'])
autre chose:
affirmer kwargs['commande'] dans le Paquet.RTCINET_COMMANDS.les valeurs de() et kwargs['commande'] dans le Paquet.RTCINET_COMMANDS.les valeurs de(), 'Undefined protocole de commande"
affirmer isinstance(kwargs['data'], bytearray), 'type non valide pour le champ de données'
pour le domaine de l'in ('commande', 'commande', 'données'):
setattr(self, '_' + champ, kwargs[champ])

    self._tag_start = Packet.TAG_START
self._version = Packet.VERSION_CURRENT % (Packet.USHRT_MAX + 1)
self._checksum = Packet.CRC_INIT
self._connection_id = kwargs.get('connection_id', 0) % (Packet.USHRT_MAX + 1)
self._packet_seq = Packet.PACKET_SEQ
Packet.PACKET_SEQ = (Packet.PACKET_SEQ + 1) % (Packet.USHRT_MAX + 1)
self._guid = uuid.uuid4().bytes
dt = datetime.datetime.now()
self._timestamp_sec = int(time.mktime(dt.timetuple()))
self._timestamp_microsec = dt.microsecond
# self._command = kwargs['command']
self._command_seq = kwargs.get('command_seq', 0)
# self._subcommand = kwargs['subcommand']
self._data_seq = kwargs.get('data_seq', 0)
self._data_length = len(kwargs['data'])
self._username = Packet.USERNAME            #Saman
self._password = Packet.PASSWORD

J'ai fait en sorte que j'ai lu tous les champs dans le bon ordre, comme il a été écrit dans le paquet par le programme client. mais encore, je ne parvenais pas à résoudre ce problème.

Avez-vous une idée de comment cela pourrait être résolu?

  • Eh bien... quelle est la durée d' buf, et ne fait que la longueur de correspondre à ce que vous attendez?
  • Pourquoi faites-vous appel à str(buf) tous les coins? Le struct veut un bytes ou bytearray ou d'autres tampon compatible, et vous avez un bytearray. L'appel de str sur qui transforme tout votre tampon dans une chaîne de caractères comme "bytearray(b'\\x00\\x00\\x00\\x00\\x00\\x00\\x00@')", ce qui n'est évidemment pas de la même longueur que le réel tampon en général.
  • Je pense que le assert() au début c'est pas une bonne idée. Il existe plusieurs autres types de mise en œuvre de la mémoire tampon de l'API d'ailleurs bytearray, donc cela peut rejeter parfaitement les valeurs valides. Si la valeur donnée ne permet pas de mettre en œuvre la mémoire tampon de l'API de la première unpack() va soulever l'exception appropriée de toute façon.
InformationsquelleAutor Saman | 2015-04-29