如何在C中读取可变长度的UDP数据包

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

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

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

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

您可以将MSG_PEEK传递给recvfrom以确切了解缓冲区需要多大的数据。 所以只需从MSG_PEEK的几个字节中重新找到numInt然后从真实事物中numInt (这次没有MSG_PEEK )。

该标准说明了MSG_PEEK ,但kernel.org更好地说明了这一点:

MSG_PEEK

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

很明显,在某些时候你会开始怀疑是否值得花费更多的系统调用来节省内存。 我认为不是。

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

你可以尝试使用一个小的缓冲区,只要设置了MSG_PEEK标志,就可以得到numInt 。 然后你可以找到你真正需要的大小,并在没有MSG_PEEK情况下再次接收以获得整个事情。

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