【发布时间】:2018-06-05 07:54:11
【问题描述】:
我有处理发送和接收 UDP 数据包的 C++ 类。到目前为止,我使用它们来发送信号(PING、WAKEUP、...),换句话说,是非常小的数据包,从来没有出现过问题。
现在我想发送大块数据(即 0.5Mb),但为了优化丢包的可能性,我希望能够自己进行分段。首先我写了一个函数,它给了我 MTU 大小:
int udp_server::get_mtu_size() const
{
if(f_mtu_size == 0)
{
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
if(ioctl(f_socket, SIOCGIFMTU, &ifr) == 0)
{
f_mtu_size = ifr.ifr_mtu;
}
else
{
f_mtu_size = -1;
}
}
return f_mtu_size;
}
注意:我知道这个函数忽略的 PMTUD。如下所述,这是为了在受控网络上工作,因此 MTU 路径不会仅仅在我们身上改变。
这个函数在Linux下很可能返回1500。
真正不清楚并且在许多答案之间似乎相互矛盾的是,这 1,500 字节的大小不仅仅是我的有效负载。它可能包括一些我无法控制的标头(即以太网标头 + 页脚、IPv4 标头、UDP 标头。)
从其他一些问题和答案来看,假设我所有的 MTU 都是 1,500,我感觉我可以发送 1,500 字节的数据而不会产生碎片。
那么...哪个是真的?
我的数据缓冲区的大小可以等于
MTU我的数据缓冲区必须是
MTU - sizeof(various-headers/footers)
附:网络是我们 100% 控制的 LAN。数据包将使用 UDP 多播从一台主计算机传输到一组从属计算机。两者之间只有一个 1Gbps 交换机。仅此而已。
【问题讨论】:
-
普遍接受的 UDP 有效负载的非分段限制为 534 字节。
-
绝对小于 MTU。可能重复:stackoverflow.com/questions/4218553/…
-
@PaulSanders,是的。非常接近,尽管被选为答案的答案非常混乱。它没有回答如何编写 C/C++ 代码来获得正确的结果。我把我自己的答案和我的发现一起放在这里。
-
简单的答案是假设路径 MTU 是 576 的最小值,如 RFC 1122/3 中所规定的那样,不确定是哪个,然后从那里开始。
-
@EJP,是的,但这并不是最佳选择。不过,我想我没有在我的问题中指定这一点......