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

Go语言使用SendMsg()传递CMSG时触发无效参数错误求助

解决Go中使用SO_TIMESTAMPING类型CMSG调用Sendmsg时的"Invalid argument"错误

你的代码出现"Invalid argument"错误的核心原因有两个:

  1. CMSG缓冲区长度不足:SO_TIMESTAMPING需要内核写入时间戳数据,你只分配了Cmsghdr结构体本身的空间,没有预留数据缓冲区,内核无法写入时间戳,因此返回参数无效。
  2. 未配置Socket选项:需要先通过SO_TIMESTAMPING选项告知内核,你需要获取发送数据包的时间戳,否则内核不处理对应的CMSG请求。

以下是修正后的完整代码示例:

import (
    "syscall"
    "unsafe"
    "time"
)

func sendWithTimestamp(fd int, pkt []byte, dstAddr syscall.Sockaddr) (time.Time, error) {
    // 配置Socket选项,请求生成软件层面的发送时间戳
    // 若需要硬件时间戳,可替换为SOF_TIMESTAMPING_TX_HARDWARE(需网卡支持)
    timestampFlags := syscall.SOF_TIMESTAMPING_TX_SOFTWARE | syscall.SOF_TIMESTAMPING_SOFTWARE
    if err := syscall.SetsockoptInt(fd, syscall.SOL_SOCKET, syscall.SO_TIMESTAMPING, timestampFlags); err != nil {
        return time.Time{}, err
    }

    // SO_TIMESTAMPING会返回3个timespec结构(发送时间、确认时间、硬件时间)
    // 计算CMSG总长度:Cmsghdr头部 + 3个timespec的空间(自动处理内存对齐)
    cmsgTotalLen := syscall.CmsgLen(3 * unsafe.Sizeof(syscall.Timespec{}))
    // 分配足够的CMSG缓冲区
    cmsgBuf := make([]byte, cmsgTotalLen)

    // 初始化Cmsghdr结构体
    cmsg := (*syscall.Cmsghdr)(unsafe.Pointer(&cmsgBuf[0]))
    cmsg.Level = syscall.SOL_SOCKET
    cmsg.Type = syscall.SO_TIMESTAMPING
    cmsg.Len = uint64(cmsgTotalLen)

    // 调用Sendmsg发送数据包并获取时间戳
    if err := syscall.Sendmsg(fd, pkt, cmsgBuf, dstAddr, 0); err != nil {
        return time.Time{}, err
    }

    // 从CMSG缓冲区中解析出发送时间戳(取第一个timespec即可)
    tsArray := (*[3]syscall.Timespec)(unsafe.Pointer(syscall.CmsgData(cmsg)))
    sendTime := time.Unix(tsArray[0].Sec, tsArray[0].Nsec)
    return sendTime, nil
}

关键细节说明

  • CMSG长度计算:必须使用syscall.CmsgLen()计算总长度,它会自动处理不同平台的内存对齐要求,避免因对齐错误导致的参数无效。
  • 时间戳类型选择:SOF_TIMESTAMPING_TX_SOFTWARE表示由内核软件生成时间戳,兼容性更好;SOF_TIMESTAMPING_TX_HARDWARE需要网卡支持硬件时间戳,精度更高。
  • 数据解析:Sendmsg调用完成后,内核会将时间戳写入你预先分配的CMSG缓冲区,直接解析即可得到发送时间。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 08:05:56