我正在运行一个运行嵌入式Linux的系统。我试图从我在套接字上接收的流中获取数据包时间戳。
创建套接字后,我执行以下操作:
if (fd != -1) {
int enabled = 1;
setsockopt(fd, SOL_SOCKET, SO_TIMESTAMP, &enabled, sizeof(enabled);
}
之后我绑定套接字,套接字的类型为SOCK_STREAM。我通过调用函数recv(fd, buf, size, 0)
成功地在套接字上接收数据。现在,为了获得接收数据的时间戳,我目前正在尝试以下方法:
ret = recv(fd, buf, size, 0);
if (ret > 0) {
struct timeval tv_ioctl;
tv_ioctl.tv_sec = 0;
tv_ioctl.tv_usec = 0;
int error = ioctl(fd, SO_TIMESTAMP, &tv_ioctl);
printf("%ld.%ld - error = %d", (long int)tv_ioctl.tv_sec,
(long int)tv_ioctl.tv_usec, error);
}
printf语句的输出始终如下:
0.0 error = -1
错误= -1表示ioctl调用失败。我已使用getsockopt
执行测试以检查是否设置了SO_TIMESTAMP选项,getsockopt
为选项SO_TIMESTAMP返回0,因此它似乎已正确设置。我有点迷失在这里,我怎么能进一步调查为什么ioctl调用似乎失败了?
答案 0 :(得分:5)
检索套接字上最新时间戳的ioctl是SIOCGSTAMP
; SO_TIMESTAMP
是套接字选项,而不是ioctl。您的代码应为:
int error = ioctl(fd, SIOCGSTAMP, &tv_ioctl);
^^^^^^^^^^
检索时间戳的备用方法是将recv
更改为recvmmsg
并从辅助数据中提取时间戳。这样更有效,因为它涉及更少的系统调用(Socket reading and timestamps);但是,ioctl更简单。
请注意,SIOCGSTAMP和SO_TIMESTAMP是互斥的 - 如果您要使用SIOCGSTAMP,则应禁用 SO_TIMESTAMP(使用enabled = 0
)。这是因为SO_TIMESTAMP指示内核通过recvmmsg
辅助数据而不是通过SIOCGSTAMP来提供时间戳。