我正在从事一个涉及 VxWorks 设备和 Linux 机器之间的 UDP 套接字通信的项目。在这个项目中,我想利用 UDP 标头的校验和字段。
似乎在 VxWorks 套接字接口中,checksum
默认启用了传出 UDP 数据包字段。
但是,对于通常的 Unix 套接字接口,似乎没有任何标志或其他方法可以打开 UDP 套接字来检查传入数据包的校验和并为传出数据包填充它。
对于通常的 Unix 套接字接口,是否存在这样的标志?
谢谢!
我正在从事一个涉及 VxWorks 设备和 Linux 机器之间的 UDP 套接字通信的项目。在这个项目中,我想利用 UDP 标头的校验和字段。
似乎在 VxWorks 套接字接口中,checksum
默认启用了传出 UDP 数据包字段。
但是,对于通常的 Unix 套接字接口,似乎没有任何标志或其他方法可以打开 UDP 套接字来检查传入数据包的校验和并为传出数据包填充它。
对于通常的 Unix 套接字接口,是否存在这样的标志?
谢谢!
(我不是专家。以下可能完全错误。)
网络接口(或驱动程序或类似的东西)应该检查传入数据包的校验和。所有位为零的校验和表示“传出接口未生成校验和”。接口必须检查任何其他校验和(包括所有位为 1,也就是校验和字段使用的补码编码中的“负零”),如果检查失败,则必须丢弃数据包。
因此,您永远不能禁用对传入数据包的 UDP 校验和检查(如果这些数据包提供了校验和)。这只是 UDP 标准的强制性部分。
接收接口可以丢弃没有校验和的数据包,[1]或者可以将它们传递给应用程序(或者可以让应用程序配置其所需的行为,尽管如果可能的话,我不知道该怎么做)。
您唯一可能能够控制的是发送接口是否在传出数据包上生成校验和。它将是特定于平台的。我在下面收集了一些方法,它们可能有效,也可能无效;警告讲师。
如果您只是采用您平台的默认行为,您将默认生成 UDP 校验和——我会在上面投入资金。
这篇 1999 年的 comp.protocols.tcp-ip 帖子ndd
表明,在 Solaris 上,您可以通过命令行全局禁用对传出数据包生成 UDP 校验和:
ndd -set /dev/udp udp_do_checksum 0
该ndd
实用程序特定于 Solaris 内核,在 Linux 或 FreeBSD 上不存在。此外,即使是 Solaris 文档也说:
udp_do_checksum
This parameter controls whether UDP calculates the checksum
on outgoing UDP/IPv4 packets.
Default
1 (enabled)
When to Change
Do not change this parameter.
(在 Linux 和 FreeBSD 上,/dev/udp
“并不真正存在”;这是 Bash 提供的虚构。我不知道/dev/udp
在 Solaris 上是否“真正存在”。)
Microsoft 的文档暗示,在 Windows 上,您可以使用记录的选项以编程方式在每个套接字的基础上禁用 UDP 校验和生成:
DWORD trueValue = 1;
int rc = setsockopt(fd, IPPROTO_UDP, UDP_NOCHECKSUM, (const char*)&yes, sizeof yes);
if (rc != 0) { perror("setsockopt"); abort(); }
该线程意味着在 FreeBSD(例如 Mac OS X)上,您可以使用其他未记录的(但截至 2018 年 1 月)选项以编程方式在每个套接字上禁用校验和生成:
int yes = 1;
int rc = setsockopt(sock, IPPROTO_UDP, UDP_NOCKSUM, (void*)&yes, sizeof yes);
if (rc != 0) { perror("setsockopt"); abort(); }
最后,这个线程意味着在 Linux 上,您可以使用其他未记录的(但截至 2018 年 1 月存在)选项以编程方式在每个套接字上禁用校验和生成:
int yes = 1;
int rc = setsockopt(sock, SOL_SOCKET, SO_NO_CHECK, (void*)&yes, sizeof yes);
if (rc != 0) { perror("setsockopt"); abort(); }