通过对套接字文件描述符的 ioctl 调用获取数据包时间戳
Obtain packet timestamp through ioctl call on socket file descriptor
我正在开发 运行 嵌入式系统 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
error = -1表示ioctl调用失败。我已经用 getsockopt
进行了测试,以检查是否设置了 SO_TIMESTAMP 选项,getsockopt
returns 0 用于 SO_TIMESTAMP 选项,因此它似乎设置正确。我在这里有点迷路,我该如何进一步调查为什么 ioctl 调用似乎失败了?
用于检索套接字上最新时间戳的 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 使时间戳可用。
我正在开发 运行 嵌入式系统 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
error = -1表示ioctl调用失败。我已经用 getsockopt
进行了测试,以检查是否设置了 SO_TIMESTAMP 选项,getsockopt
returns 0 用于 SO_TIMESTAMP 选项,因此它似乎设置正确。我在这里有点迷路,我该如何进一步调查为什么 ioctl 调用似乎失败了?
用于检索套接字上最新时间戳的 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 使时间戳可用。