【发布时间】:2020-12-14 17:43:43
【问题描述】:
我正在尝试使用带有 GSO(通用分段卸载)的 UDP 来发送 50Kb 大小的数据包。
// sender side
int val = 1472; // ETHERNET - udp - upv4 header
if (setsockopt(fdt, SOL_UDP, UDP_SEGMENT, &val, sizeof(val)))
error(1, errno, "setsockopt udp segment");
int ret = sendmsg(fd, msg, flags);
关于recv大小,我愿意
// recv side
int ret = recvmsg(fd, msg, flags);
我可以看到我发送了 50Kb 的消息,而接收方只收到了 1472 个呼叫。我听说过 GRO(通用接收卸载),但我没有在网上找到任何示例。我是否必须进行多个系统调用才能获取所有数据,是否可以设置一个 socekt 选项或进行系统调用以一次性接收重新组装的消息?如果我必须进行多个系统调用,而不是仅仅依靠 IP 分片并发送大于 MTU 的数据包,如何才能更有效?
【问题讨论】:
-
发送过大的 UDP 数据包不是我所相信的,尤其是中间可能有多少层 NAT 和状态防火墙。您不能将传输分割成更小的块或使用 TCP 流式传输吗?
-
作为注释 1472 (ish) 是关于您对分段数据包序列的第一个数据包的期望。
-
@tadman:我确信一个 recvmsg 只收到了分段消息序列中第一个数据包的 1472 个,我认为 UDP GRO 应该重新组装所有分段数据包并返回整个消息。
-
@tadman:此外,数据通过以太网在直接连接的 ECU 之间传输。没有重新路由,NAT 或任何东西。 1472 几乎是我们可以发送的最大安全数据包。
-
UDP 数据报理想情况下约为 576 个八位字节,并且您永远不会希望发送导致数据包大于您的路径 MTU 的数据报(您可以使用 PMTUD 发现最小的 MTU路径)。您将丢失数据报,它们越小,您丢失的越少。此外,智能站点现在有防火墙丢弃数据包碎片(第一个通过,但其余的碎片被丢弃)以防止碎片攻击。
标签: c++ c networking tcp udp