unpack_from 需要至少 4 个字节的缓冲区

2024-01-11

我收到来自客户端的数据包,其中包含许多字段。我成功读取了所有字段,但是当涉及到最后一个字段 tag_end 时,python 给了我一个错误:

unpack_from 需要至少 4 个字节的缓冲区未找到。

这是代码:

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')

这是代码中使用的一些常量:

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)

以及数据包对象的初始化,其中初始化字段:

def init(自我,**kwargs): 如果 kwargs 中的“buf”: self.set_bin(kwargs['buf']) 别的: 在 Packet.RTCINET_COMMANDS.values() 中断言 kwargs['command'] 和 Packet.RTCINET_COMMANDS.values() 中的 kwargs['subcommand'], '未定义的协议命令' 断言 isinstance(kwargs['data'], bytearray), '数据字段类型无效' 对于('命令','子命令','数据')中的字段: setattr(self, '_' + 字段, kwargs[字段])

    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

我已确保以正确的顺序读取所有字段,因为它是由客户端程序写入数据包中的。但我仍然无法解决这个问题。

您知道如何解决这个问题吗?


问题似乎是你正在将东西转换为str无缘无故地到处都是。

在某些地方,比如PACKER_1 = struct.Struct(str(STRUCT_FORMAT_STR_1)),它使您的代码可读性和理解性较差,但不会影响实际输出。例如,STRUCT_FORMAT_STR_1已经是一个str, so str(STRUCT_FORMAT_STR_1)是一样的str.

但在其他地方,情况却远比这糟糕。特别是,看看所有的行,比如Packet.PACKER_1.unpack_from(str(buf), offset)。那里,buf is a bytearray。 (一定是这样,因为你assert它。) 打电话str on a bytearray为您提供该字符串的表示形式bytearray。例如:

>>> b = bytearray(b'abc')
>>> len(b)
3
>>> s = str(b)
>>> s
"bytearray(b'abc')"
>>> len(s)
17

该字符串表示显然通常不会与您所表示的实际缓冲区具有相同的长度。因此,您会收到有关长度错误的错误也就不足为奇了。 (如果你真的很不幸并且没有任何此类错误,那么你会读取垃圾值。)

那么,你应该做什么来转换bytearray进入某事struct模块可以处理吗?没有什么!作为the docs https://docs.python.org/3/library/struct.html say:

多个结构函数(以及 Struct 的方法)采用缓冲区参数。这是指实现缓冲区协议并提供可读或可读写缓冲区的对象。用于此目的的最常见类型是bytes and bytearray

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

unpack_from 需要至少 4 个字节的缓冲区 的相关文章

随机推荐

  • Javascript - 生成范围内的随机数,不包括某些数字

    基本上我正在创建一个网格并在其上绘制点 并且没有两个点可以位于完全相同的位置 3 4 与 4 3 不同 y 坐标必须在 2 和 7 之间 因此 2 3 4 5 6 7 x 坐标必须在 1 和 7 之间 我有一个 getRandom 函数 如
  • Python:BaseHTTPRequestHandler - 阅读原始文章

    如何阅读原始 http 帖子 STRING 我找到了几种用于读取帖子的解析版本的解决方案 但是我正在处理的项目提交了没有标头的原始 xml 有效负载 所以我试图找到一种方法来读取发布数据 而不将其解析为键 gt 值数组 self rfile
  • ByteBuffer 到 bigdecimal、二进制、字符串

    请检查本文底部的编辑我有一个字节缓冲区 128 位 其中有数字 我需要将其转换为大十进制 二进制 字符串 因为这些是使用 jdbc 时相应的 sql 映射 我可以使用库 API 来执行此操作吗 我看到 String valueof 不接受字
  • PHP CS Fixer File Watcher 导致 PHPStorm 中的文件缓存冲突

    I use a 文件观察者定义为这样 这是我的watchers xml file
  • 查找窗口错误 183

    有谁知道什么会导致FindWindow http msdn microsoft com en us library windows desktop ms633499 28v vs 85 29 aspx返回错误的函数 ALREADY EXIS
  • Flutter Web中如何获取本地IP

    我正在尝试在 Flutter Web 应用程序中获取本地 IP 地址 在互联网上搜索我发现了这个包 get ip0 4 0 它声明它正在网络下工作 我有这个功能 Future
  • C# 在运行时启用/禁用网络跟踪?

    在示例中 我可以发现跟踪是通过配置文件启用的 例如
  • 正确使用cudaDeviceReset()

    由于我怀疑 黑匣子 GPU 在一些较大的代码中没有完全关闭 其他人也许也是 https stackoverflow com questions 10294595 handling ctrlc exception with gpu 我会包括一
  • php - array_fill 负索引

    使用时php 数组填充 http php net manual en function array fill php和负指数 为什么php只填充第一个负索引 然后跳转到0 例如 array fill 4 4 10 应该填满 4 3 2 1
  • Windows 8 Consumer Preview + Visual Studio 11 Developer Preview 中的套接字 BUG

    我正在 Visual Studio 11 开发人员预览版中编写一个应用程序 在该应用程序使用 reader InputStreamOptions InputStreamOptions Partial 运行一段时间后出现此错误 选项集 An
  • Docker 镜像损坏?删除图层?

    系统重新启动后 现有的 docker 映像似乎已损坏 我尝试了以下方法 在该机器内重建一个泊坞窗 这有效 该图像运行良好 我拉了一个已经存在的图像 它说图层已经存在 但这个图像似乎仍然被损坏了 我觉得删除图像会有帮助 当我尝试删除时 似乎只
  • Pandas-创建一个新列,填充另一列中的观察数量

    我有一个 DataFrame 对象df 中的列值之一df is ID有许多行具有相同的 ID 我想创建一个新列num totals计算每个 ID 的观察次数 例如 这样的事情 ID Num Totals 1 3 1 3 1 3 2 2 2
  • 如何使用 Jersey (JAX-RS 2.0) 客户端启用 gzip 压缩以进行内容编码?

    我有一个使用 JAX RS 2 0 的 Jersey 实现的 Java 应用程序 我想在客户端启用 gzip 压缩 服务器已启用它 并且我已通过在 Chrome 中查看开发人员工具中客户端正在使用的特定 URL 的 大小 内容 来验证这一点
  • 自定义 UITextField 委托设置为 self 启动无限循环

    我正在编写 iPhone 应用程序 其中需要自定义 UITextField 类 对于我的文本字段 我需要缩进 文本之前的图像和最大字符数 为此 我创建了基于 UITextField 的自定义类 我所有的文本字段都将基于这个新类 我使用 Go
  • 如何从 Javascript 中的 HH:MM AM 时间字符串中减去小时?

    从格式如下的时间字符串中减去几个小时的最佳方法是什么 8 32 AM 我考虑过在冒号处拆分字符串 但是当从上午 1 00 减去 3 小时时 我得到 2 00 AM 而不是所需的晚上 10 00 最可靠的方法是将其转换为JS日期对象 然后你对
  • CMake 错误:在 Windows 上执行 make 失败

    我在尝试构建时遇到错误纳米信息项目 https github com nanomsg nanomsg在 Windows 7 中 cmake Building for NMake Makefiles The C compiler identi
  • 如何在php中验证正确的域名和子域

    如何去除www and validate有效的域名 有效域名 domain com subdomain domain com sub domain domain com 无效域名 www domain com www subdomain d
  • 我验证用户 Android 应用内订阅的步骤是否正确?

    我正在制作一个不需要用户帐户 登录的应用程序 并允许用户购买订阅 我想使用 Google Play 开发者 API 来验证用户是否已购买 有效订阅 从所有文档中 我收集了以下步骤 它们是否正确 您能回答其中的两个问题吗 创建一个服务帐号 h
  • 使用容器/堆实现优先级队列

    从整体上看 我正在尝试使用优先级队列来实现 Dijkstra 算法 根据 golang nuts 成员的说法 在 Go 中执行此操作的惯用方法是使用具有自定义底层数据结构的堆接口 所以我创建了 Node go 和 PQueue go 如下所
  • unpack_from 需要至少 4 个字节的缓冲区

    我收到来自客户端的数据包 其中包含许多字段 我成功读取了所有字段 但是当涉及到最后一个字段 tag end 时 python 给了我一个错误 unpack from 需要至少 4 个字节的缓冲区未找到 这是代码 def set bin se