在每个片段上使用UDP标头发送碎片数据报

时间:2015-02-06 21:17:42

标签: c sockets networking udp ip

我正在使用一个必须能够使用UDP与传统计算机进行通信的嵌入式盒子。当该框发送大型UDP消息(需要分段)时,每个片段都包含一个UDP头。因此,如果我想发送一个大型数据报,它将像这样分段:

[eth hdr][ip hdr][udp hdr][    data 1    ] /* first fragment */
[eth hdr][ip hdr][udp hdr][    data 2    ] /* second fragment */
[eth hdr][ip hdr][udp hdr][  data 3  ]     /* last fragment */

我知道这不是习惯,因为通常udp标头只会包含在碎片消息的第一个ip数据包中。但是,这非常适合与我需要交谈的其他机器进行通信(例如使用recvfrom),因此我没有理由深入研究并试图改变它。

然而,我的问题是阅读邮件。该框似乎期望以相同的方式将碎片化的udp数据报发送给它。我的意思是它希望每个ipv4片段都有一个udp头。在尝试更改它(它是一个相当专业和复杂的平台)之前,我想知道是否有任何方法可以配置sendto()或任何其他此类函数以此格式发送udp消息。我在监视流量时看到那些udp标头不存在。

非常感谢您的帮助。

1 个答案:

答案 0 :(得分:1)

没有。 Socket不会以这种方式工作。只需编写自己的sendto包装器,即可在您选择的任何缓冲区大小边界上跨多个UDP数据包手动分段帧。这将达到您想要的效果。

示例代码如下:

ssize_t fragmented_sendto(int sockfd, const void *buf, size_t len, int flags,
           const struct sockaddr *dest_addr, socklen_t addrlen, size_t MAX_PACKET_SIZE)
{
    unsigned char* ptr = (unsigned char*) buf;

    size_t total = 0;

    while (total <= len)
    {
       size_t newsize = len - total;
       if (newsize > MAX_PACKET_SIZE)
       {
           newsize = MAX_PACKET_SIZE;
       }
       ssize_t result = sendto(sockfd, ptr, newsize, flags, dest_addr, addrlen);
       if (result < 0)
       {
          // handle error
          return -1;
       }
       else
       {
          total += result;
          ptr += result;
       }
    }
    return (ssize_t)total;
}