c - 使用 SCM_TIMESTAMP 在 macOS 上启用 UDP 数据包时间戳
问题描述
我尝试在 macOS(和 iOS)上启用硬件 UDP 数据包时间戳,但无法使其正常工作(在 macOS 10.13.4、Xcode 9.3 上工作)。
我的目标是为传出和传入的 UDP 数据包获取尽可能精确的时间戳,理想情况下相当于可以在 Linux上请求的纳秒时间戳SO_TIMESTAMPNS
。
下面的示例适用于 Linux,但不适用于 macOS,其中尝试请求SCM_TIMESTAMP
选项失败并-1
返回setsockopt()
调用代码。
我知道 macOS 中的套接字实现遵循 POSIX(因此不希望SO_TIMESTAMPNS
工作),但我很惊讶我什至无法开始SCM_TIMESTAMP
工作(也因为我SCM_TIMESTAMP
在我的 中找到了定义sys/socket.h
):
// testing SCM_TIMESTAMP
#include <stdio.h>
#include <sys/socket.h>
int main() {
// open socket
int sd, ret, optval;
socklen_t len;
sd = socket(AF_INET, SOCK_DGRAM, 0);
if (sd < 0) {
fprintf(stderr, "failed to open socket: %d\n", sd);
return 1;
}
// set SCM_TIMESTAMP
optval = 1;
ret = setsockopt(sd, SOL_SOCKET, SCM_TIMESTAMP, &optval, sizeof(optval));
if (ret < 0) {
fprintf(stderr, "request for setting SCM_TIMESTAMP failed: %d\n", ret);
return 1;
}
// get SCM_TIMESTAMP
optval = 0;
len = 0;
ret = getsockopt(sd, SOL_SOCKET, SCM_TIMESTAMP, &optval, &len);
if (ret < 0) {
fprintf(stderr, "request for getting SCM_TIMESTAMP failed: %d\n", ret);
return 1;
}
fprintf(stderr, "SCM_TIMESTAMP: %d %d\n", optval, len);
return 0;
}
我有什么明显的遗漏吗?我可以在 macOS 和 iOS 上获得的最精确的时间戳是什么?
任何帮助表示赞赏!
编辑:
我发现 UDP 时间戳功能应该是不久前添加到 NetBSD 中的,但在 macOS 上找不到任何信息。
解决方案
您正在寻找的常数是SO_TIMESTAMP
。SCM_TIMESTAMP
用于指定套接字级别的控制消息类型。SO_TIMESTAMP
用于指定一个套接字选项。
附带说明一下,在代码片段的末尾打印 optval 和 len,但即使 setsockopt 和 getsockopt 有效,您也将始终打印0 0
在那里。通过将指针0
作为最后一个参数传递给 getsockopt,您可以告诉它倒数第二个参数 (optval) 的缓冲区大小为 0,从而完全禁止它使用它。如果您将 len 设置为sizeof(int)
,它会将您指定的选项的值复制到 optval 中,正如您所期望的那样。
推荐阅读
- reactjs - 使用 ExploreContainer 模板在 Ionic React 中进行编程导航
- docker - 在 docker 中运行时,Django 休息框架大摇大摆地缺少端口
- python - 将 pandas 数据框/系列应用于 netaddr EUI 构造函数
- php - $_POST 命令无法识别多选图像复选框值
- python - 如何证明递归适用于所有数字?
- node.js - 运行“npm run build”时出现 npm run build 错误
- javascript - 在 React 中的 history.push() 时无法设置新组件的状态
- php - Laravel Eloquent 查询嵌套关系
- c# - 使用 JsonConverter 将 Null 属性设置为空字符串 - System.Text.Json
- uno-platform - Skia.Gtk 上的 Uno Platform App 文本渲染问题