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

macOS下Python用socket.sendto()发送手工数据包遇Errno22求助

macOS下Raw Socket发送数据包报错OSError: [Errno 22] Invalid Argument的原因与解决方法

核心原因分析

macOS对RAW套接字的限制和Linux存在显著差异,触发该错误的常见原因包括:

  • IP头字段校验严格:使用IPPROTO_RAW创建的套接字要求构造的IP头完全符合系统规范,哪怕微小错误(如校验和、总长度计算错误)都会触发参数无效
  • 端口参数隐性要求:sendto中传入的端口设为0可能不符合macOS套接字实现的隐性规则
  • IP_HDRINCL行为差异:开启IP_HDRINCL后,系统不会自动修正IP头的错误,只会严格校验并拒绝不符合要求的数据包

具体解决步骤

  1. 严格校验IP头关键字段
    确保IP头的以下字段完全正确:

    • 版本号(version):必须为4(IPv4)
    • 头部长度(IHL):以32位字为单位计算,20字节标准IP头对应IHL=5
    • 总长度(total_length):等于IP头长度+传输层数据总字节数
    • 校验和(checksum):必须准确计算,不能留空或使用错误值
      可使用以下代码计算IP头校验和:
    def calculate_ip_checksum(ip_header):
        checksum = 0
        # 按16位分组求和
        for i in range(0, len(ip_header), 2):
            word = (ip_header[i] << 8) + (ip_header[i+1] if i+1 < len(ip_header) else 0)
            checksum += word
        # 折叠进位并取反
        checksum = (checksum >> 16) + (checksum & 0xffff)
        checksum += checksum >> 16
        return ~checksum & 0xffff
    
  2. 调整sendto的端口参数
    将sendto中的端口从0改为合法传输层端口(与构造的TCP/UDP头目标端口一致即可):

    sent_bytes = sock_send.sendto(packet.tobytes(), (Destination_Address, 80))
    
  3. 替换协议族标识(可选)
    macOS中PF_INET是协议族的标准标识,替换AF_INET可能解决隐性兼容问题:

    sock_send = socket.socket(socket.PF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
    
  4. 以root权限运行程序
    RAW套接字需要管理员权限,执行脚本时添加sudo:

    sudo python3 your_script.py
    

额外验证建议

用Wireshark抓取本地发送的数据包,对比IP头字段与系统规范的一致性,重点排查校验和、总长度等容易出错的字段。

内容的提问来源于stack exchange,提问作者Daniel Muntean

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 12:30:01