You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用struct.pack触发struct.error: required argument is not an integer错误排查

解决struct.pack时的"required argument is not an integer"错误

这个错误指向很明确:你传给struct.pack的某个参数不符合格式符要求的整数类型,咱们一步步排查解决:

首先定位问题参数

struct.pack('!BBHHHBBH4s4s', ...)里的格式符对应要求:

  • B:无符号整数(0-255范围)
  • H:无符号短整数(0-65535范围)
  • 4s:4字节字节串(这个没问题,报错和它俩无关)

所以问题肯定出在version_IHL、TOS、totalLength、ID、flags、TTL、protocolNR、checksum这8个参数里的某一个。

先在打包代码前加一段打印,快速定位非整数的参数:

# 打印所有参数的类型和值,排查异常项
params = [
    ("version_IHL", version_IHL), ("TOS", TOS), ("totalLength", totalLength),
    ("ID", ID), ("flags", flags), ("TTL", TTL), ("protocolNR", protocolNR),
    ("checksum", checksum), ("sourceAddress", sourceAddress), ("destinationAddress", destinationAddress)
]
for name, val in params:
    print(f"{name}: type={type(val)}, value={val}")

常见问题及修复方案

  1. 参数是字符串而非整数
    比如你修改TTL时不小心写成了TTL = "64"而不是TTL = 64,直接转成整数即可:
TTL = int(TTL)
# 如果是十六进制字符串,加上base参数:int("40", 16)
  1. 参数是字节串而非整数
    如果是从原始数据包解包后处理时,不小心保留了字节类型(比如直接截取了IP头的某字节),用int.from_bytes转换:
# 假设version_IHL是1字节的bytes,转成大端整数
version_IHL = int.from_bytes(version_IHL, byteorder='big')
  1. flags参数处理错误
    IP头里的flags字段实际是16位的"标志+分片偏移"组合值,如果你拆分修改了标志位,一定要重新组合成16位整数:
# 示例:设置DF(不分片)标志,保留原偏移
original_flags_offset = 0x1234  # 从解包得到的整数
new_flags = 0x4000  # DF位的对应值
flags = new_flags | (original_flags_offset & 0x1FFF)  # 保留低13位的偏移值
  1. checksum未正确计算
    修改数据包后原校验和会失效,必须重新计算成16位整数,不能用字符串或其他类型。这里给你一个标准的IP校验和实现:
def calculate_ip_checksum(ip_header):
    checksum = 0
    # 将IP头按16位分组求和
    for i in range(0, len(ip_header), 2):
        if i + 1 < len(ip_header):
            word = (ip_header[i] << 8) + ip_header[i+1]
            checksum += word
    # 处理进位:将高16位加到低16位
    checksum = (checksum >> 16) + (checksum & 0xFFFF)
    # 取反并保留16位
    checksum = ~checksum & 0xFFFF
    return checksum

# 先打包校验和为0的临时头,计算后再打包最终头
temp_header = struct.pack('!BBHHHBBH4s4s', version_IHL, TOS, totalLength, ID, flags, TTL, protocolNR, 0, sourceAddress, destinationAddress)
checksum = calculate_ip_checksum(temp_header)
ip_header = struct.pack('!BBHHHBBH4s4s', version_IHL, TOS, totalLength, ID, flags, TTL, protocolNR, checksum, sourceAddress, destinationAddress)

最后提醒

修改数据包后,不仅IP头的校验和要重新计算,传输层(比如TCP/UDP)的校验和也需要重新计算,不然转发后的数据包会被目标主机直接丢弃哦。

内容的提问来源于stack exchange,提问作者JAHANZAIB MALIK

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 03:47:06