Если вы хотите, чтобы struct.unpack
возвратил данные, которые вы передали struct.pack
, то аргумент, который вы передаете struct.unpack
, должен быть объектом, возвращаемым из struct.pack
.Прямо сейчас вы даете ему пустой байтовый массив, поэтому вы возвращаете пустые данные.
Одно из возможных решений - передать упакованные данные в качестве аргумента _packet.unpack
, который вы затем передаете struct.unpack
.
import struct
class _packet:
def __init__(self, payload):
self.version = 1
self.syn = False
self.fin = False
self.reset = False
self.hasOpt = False
self.ack = 0
self.payload = payload
return
def pack(self):
return struct.pack('????i' + str(len(self.payload)) + 's', self.syn, self.fin, self.reset, self.hasOpt,self.ack, bytes(self.payload, 'utf-8'))
def unpack(self, data):
header_size = 8 #four one-byte bools and one four-byte int
return struct.unpack('????i' + str(len(packed_data)-header_size) + 's', data)
def main():
packet = _packet("Hello")
packet.ack = 249
packet.syn = True
packet.fin = True
packet.reset = True
packedData = packet.pack()
print(packedData)
unpackedData = packet.unpack(packedData)
print(unpackedData)
if __name__== "__main__":
main()
Или, возможно, вы бы предпочли назначить упакованные данные в качестве атрибута экземпляра _packet
, поэтому вызывающей стороне не нужно предоставлять никаких аргументов.
import struct
class _packet:
def __init__(self, payload):
self.version = 1
self.syn = False
self.fin = False
self.reset = False
self.hasOpt = False
self.ack = 0
self.payload = payload
self.packed_data = None
def pack(self):
self.packed_data = struct.pack('????i' + str(len(self.payload)) + 's', self.syn, self.fin, self.reset, self.hasOpt,self.ack, bytes(self.payload, 'utf-8'))
return self.packed_data
def unpack(self):
header_size = 8 #four one-byte bools and one four-byte int
return struct.unpack('????i' + str(len(packed_data)-header_size) + 's', self.packed_data)
def main():
packet = _packet("Hello")
packet.ack = 249
packet.syn = True
packet.fin = True
packet.reset = True
packedData = packet.pack()
print(packedData)
unpackedData = packet.unpack()
print(unpackedData)
if __name__== "__main__":
main()
Лично я бы сделал unpack
методом класса, поскольку вам не нужно создавать экземпляр _packet для десериализации некоторых байтов в новый объект _packet
.Я бы также сделал атрибуты объекта необязательно устанавливаемыми во время инициализации, поэтому вам не нужно присваивать им индивидуально в main
.
import struct
class _packet:
def __init__(self, payload, **kwargs):
self.version = 1
self.syn = kwargs.get("syn", False)
self.fin = kwargs.get("fin", False)
self.reset = kwargs.get("reset", False)
self.hasOpt = kwargs.get("hasOpt", False)
self.ack = kwargs.get("ack", 0)
self.payload = payload
def pack(self):
return struct.pack('????i' + str(len(self.payload)) + 's', self.syn, self.fin, self.reset, self.hasOpt,self.ack, bytes(self.payload, 'utf-8'))
#optional: nice string representation of packet for printing purposes
def __repr__(self):
return "_packet(payload={}, syn={}, fin={}, reset={}, hasOpt={}, ack={})".format(self.payload, self.syn, self.fin, self.reset, self.hasOpt, self.ack)
@classmethod
def unpack(cls, packed_data):
header_size = 8 #four one-byte bools and one four-byte int
syn, fin, reset, hasOpt, ack, payload = struct.unpack('????i' + str(len(packed_data)-header_size) + 's', packed_data)
return cls(payload, syn=syn, fin=fin, reset=reset, hasOpt=hasOpt, ack=ack)
def main():
packet = _packet("Hello", ack=249, syn=True, fin=True, reset=True)
packedData = packet.pack()
print(packedData)
unpackedData = _packet.unpack(packedData)
print(unpackedData)
if __name__== "__main__":
main()