【问题标题】:How to read UDP packet with variable length in C如何在C中读取可变长度的UDP数据包
【发布时间】:2014-04-06 18:18:34
【问题描述】:

我正在通过 UDP 发送一个 C 结构

struct packet{
    int numInt;
    int* intList; //malloc'ed as (sizeof(int)*numInt)
}

它将被序列化为[numInt][intList[0]]...[intList[numInt-1]]

我的理解是,在 UDP 上调用 recvfrom 将读取整个数据包,即使缓冲区不包含那么多字节。使用非常大的缓冲区是我唯一的选择吗?

【问题讨论】:

    标签: c serialization udp


    【解决方案1】:

    您可以将MSG_PEEK 传递给recvfrom 以准确确定缓冲区需要多大。所以只需recvfrom 几个字节和MSG_PEEK 即可找到numIntrecvfrom 真实的东西(这次没有MSG_PEEK)。

    The standard 说了一些关于 MSG_PEEK 的内容,但 kernel.org 拼写更好:

    MSG_PEEK

    该标志使接收操作从 接收队列的开始,而不从接收队列中删除该数据 队列。因此,后续的接收调用将返回相同的数据。

    很明显,在某些时候,您会开始怀疑将系统调用的数量加倍以节省内存是否值得。我认为不是。

    【讨论】:

      【解决方案2】:

      UDP 数据包作为一个整体发送和接收。 如果你收到了,尺寸是对的。您唯一需要做的就是在 read() 或 recv() 或 recfrom() 上提供足够大的缓冲区。有效载荷内的长度字段是多余的,因为 read() 会告诉你正确的大小。这也很危险,因为它依赖于具有相同字节顺序的发送方和接收方。

      【讨论】:

      • 如果发送者和接收者不理解他们的字节顺序,那有什么意义呢?
      【解决方案3】:

      您可以尝试使用一个小缓冲区,该缓冲区足够大以获取numInt,并设置MSG_PEEK 标志。然后你可以找出你真正需要的尺寸,然后在没有MSG_PEEK的情况下再次接收以获得整个东西。

      【讨论】:

        【解决方案4】:

        我很确定 recvfrom 将读取它的第三个参数 len 告诉它的字节数。如果可用的字节数较少,它将返回那里的内容。如果还有更多,它将返回最多 len 个字节。您可能需要进行额外的调用才能获取您期望的所有数据。

        【讨论】:

        • 不会投反对票,但标准说:“如果消息太长而无法放入提供的缓冲区,并且标志参数中未设置 MSG_PEEK,多余的字节应丢弃.”。 SOCK_DGRAM 在这方面与 SOCK_STREAM 不同。
        猜你喜欢
        • 1970-01-01
        • 2017-10-10
        • 1970-01-01
        • 2010-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-16
        相关资源
        最近更新 更多