我可以在一个UDP数据包中发送多少数据并仍然可以避免碎片?

时间:2018-06-05 07:54:12

标签: c++ udp mtu

我有C ++类来处理发送和接收UDP数据包。到目前为止,我用那些发送信号(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.

真正不清楚的是,许多答案之间似乎相互矛盾的是,这1500字节的大小不仅仅是我的有效载荷。它可能包括一些我无法控制的标题(即以太网标题+页脚,IPv4标题,UDP标题。)

从其他一些问题和答案来看,我觉得我可以发送1,500字节的数据而不会出现碎片,假设我的所有MTU都是1,500。

所以......哪个是真的?

  1. 我的数据缓冲区的大小可以等于MTU

  2. 我的数据缓冲区必须为MTU - sizeof(various-headers/footers)

  3. P.S。网络是我们100%控制的局域网。数据包将使用UDP多播从一台主计算机传输到一组从计算机。中间只有一个1Gbps交换机。没什么。

1 个答案:

答案 0 :(得分:1)

RFC-8085中定义的大小非常明确: UDP使用指南

https://tools.ietf.org/html/rfc8085#section-3.2

有关有效载荷的大小计算有相关位。

  

要确定适当的UDP有效负载大小,应用程序必须从PMTU大小中减去IP标头的大小(包括任何IPv4可选标头或IPv6扩展标头)以及UDP标头的长度(8个字节)。此大小称为最大段大小(MSS),可以从TCP / IP堆栈[RFC1122]获得。

所以在C / C ++中,这就变成了:

#include <netinet/ip.h> // for iphdr
#include <netinet/udp.h> // for udphdr

int mss(udp.get_mtu_size());
mss -= sizeof(iphdr);
mss -= sizeof(udphdr);

警告: IP标头的大小因选项而异。如果您使用会增加大小的选项,那么您的MSS计算必须考虑到这一点。

此处不包括以太网页眉和页脚的大小,因为它们对UDP数据包是透明的。