代码之家  ›  专栏  ›  技术社区  ›  Alexis Wilke

我可以在一个udp包中发送多少数据,同时还能避免碎片化?

  •  -1
  • Alexis Wilke  · 技术社区  · 6 年前

    我有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头)。

    从其他一些问题和答案来看,假设我所有的mtu都是1500,那么我可以发送1500字节的数据而无碎片化。

    所以…哪个是真的?

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

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

    另外,网络是我们100%控制的局域网。数据包将使用udp多播从一台主计算机传输到一组从计算机。在这两者之间只有一个1Gbps的开关。没别的了。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Alexis Wilke    6 年前

    尺寸在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数据包是透明的。