如何使用 UdpSocket 接收任意长度的数据?

How do I receive arbitrary length data using a UdpSocket?

我正在编写一个使用 UDP 发送和接收数据包的应用程序。但是,documentation of recv_from 指出:

If a message is too long to fit in the supplied buffer, excess bytes may be discarded.

有没有办法接收所有字节并将它们写入向量?我真的必须分配一个具有最大数据包长度的数组(据我所知,对于 IPv4 是 65,507 字节)以确保接收所有数据吗?这对我来说似乎有点多。

查看文档中的下一个方法,UdpSocket::peek_from(强调我的):

Receives a single datagram message on the socket, without removing it from the queue.

您可以使用它来读取固定数量的数据,例如包含整个数据包长度的前导 4 个字节。您可以使用 byteorder 获取长度作为数字,然后分配恰好正确数量的 space 并调用 recv_from.


现在,这是个好主意吗?

作为:

Because extra system calls are much more expensive than getting some space from the stack.

并且来自 the linked question

Obviously at some point you will start wondering if doubling the number of system calls to save memory is worth it. I think it isn't.

由于最近的 Spectre / Meltdown 事件,现在是提醒避免额外系统调用的好时机。

您可以像建议的那样,提前分配一个 "big enough" 数组。您需要跟踪实际读取的字节数与分配的字节数。我推荐 arrayvec 之类的东西以使其更容易。

您可以改为在堆上实现一个预先分配的缓冲区池。当您从套接字读取时,您使用缓冲区或创建一个新缓冲区。使用完缓冲区后,将其放回池中以供重复使用。这样一来,您将进行一次内存分配,并且只会在堆栈上传递小的 Vecs。

另请参阅:

  • How large should my recv buffer be when calling recv in the socket library
  • How to read UDP packet with variable length in C