使用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}")
常见问题及修复方案
- 参数是字符串而非整数
比如你修改TTL时不小心写成了TTL = "64"而不是TTL = 64,直接转成整数即可:
TTL = int(TTL) # 如果是十六进制字符串,加上base参数:int("40", 16)
- 参数是字节串而非整数
如果是从原始数据包解包后处理时,不小心保留了字节类型(比如直接截取了IP头的某字节),用int.from_bytes转换:
# 假设version_IHL是1字节的bytes,转成大端整数 version_IHL = int.from_bytes(version_IHL, byteorder='big')
- flags参数处理错误
IP头里的flags字段实际是16位的"标志+分片偏移"组合值,如果你拆分修改了标志位,一定要重新组合成16位整数:
# 示例:设置DF(不分片)标志,保留原偏移 original_flags_offset = 0x1234 # 从解包得到的整数 new_flags = 0x4000 # DF位的对应值 flags = new_flags | (original_flags_offset & 0x1FFF) # 保留低13位的偏移值
- 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
相关产品推荐
相关产品推荐

