【问题标题】:Is this the correct way to handle partial reads of UDP messages?这是处理部分读取 UDP 消息的正确方法吗?
【发布时间】:2013-10-28 16:55:29
【问题描述】:

因此,在 TCP 流的情况下,需要跟踪每个 recv 调用读取了多少消息。然后可以将部分读取拼凑在一起,最终可以正常接收消息。

但是对于 UDP 消息,应该如何处理部分读取(假设所有 UDP 消息都小到可以避免碎片)?由于部分消息的剩余数据似乎被丢弃,是否只是确保recvfrom 返回与发送的缓冲区相同的大小?如果存在差异,则意味着它是部分且有缺陷的消息,应该跳过它。

所以从概念上讲,TCP 示例需要一个循环,而 UDP 示例只需要一个 if 语句。

这是正确的吗?

【问题讨论】:

    标签: c tcp udp partial


    【解决方案1】:

    无法在 UDP 中进行部分读取。 UDP 保证接收到的数据报与发送时一样,无论是否分段,因此必须先接收到整个数据报,然后才能读取它。

    请参阅:http://en.wikipedia.org/wiki/User_Datagram_Protocol,您可以关注其中的参考资料以获取更多官方资源。

    至于读入缓冲区,您将需要一个至少与任何可能的数据报一样大小的缓冲区。或者另一种常见的方法是在数据报的开头附近包含数据报的大小,这样您就可以只读取这些字节来获取该数字,然后使用适当大小的缓冲区。

    【讨论】:

    • Datagrams – Packets are sent individually and are checked for integrity only if they arrive. Packets have definite boundaries which are honored upon receipt, meaning a read operation at the receiver socket will yield an entire message as it was originally sent. 那么这是否意味着当我收到一个数据报时,我总能确定它的大小和内容与最初发送的相同?也就是说,唯一可能发生的“错误”是数据报被完全丢弃时?在那种情况下,recvfrom 返回读取大小有什么意义?而且我并不是要刻薄,我只是想学习......
    • @c00kiemonster 您需要长度,因为您通常不知道发送了什么。
    • @c00kiemonster 因为发件人可以发送不同大小的数据报 - 这完全取决于发件人他们的数据报有多少字节,因此我说“需要一个至少大小为任何可能数据报的缓冲区 [为您application]" - 如果您收到的数据报大于您的应用程序支持的最大数据报,那么它要么是恶意的,要么是有缺陷的,所以丢弃它。
    【解决方案2】:

    不正确。如果 recv() 返回与给定相同的长度,则消息是该长度或更大。没有办法说是哪个。正确的技术是使用比预期的最大可能数据报大一号的缓冲区。那么如果你得到那个长度,那一定是发件人的错误。

    【讨论】:

    • “...缓冲区比预期的最大可能数据报大一”,这是另一种技术,即使用与您期望的最大值相同大小的缓冲区,并在您自己的标头中包含该大小。
    【解决方案3】:

    正确。但是,只有在接收方事先知道发送方正在发送多少字节的情况下,if 条件才会起作用。

    【讨论】:

    • 是的,这是真的。谢谢
    【解决方案4】:

    正如已经提到的,与这个问题密切相关的是,在将这些与数据报协议一起使用时,需要一种将适当大小(足够大)的缓冲区传递给 recv/recvmsg/recvfrom 的策略。对于 UDP,一个简单且 100% 可靠的方法是传递至少 65507 字节的缓冲区,即最大 UDP 有效负载大小。

    但是,我更喜欢一种更简洁的方法是明确询问 recv() 缓冲区需要多少字节。这样就可以实现了:

    int buflen = recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC);
    if (buflen < 0) {
        // handle error
        return;
    }
    uint8_t buf[buflen];
    rxlen = recv(sockfd, buf, buflen, 0);
    if (rxlen < 0) {
        // again, handle error
        return;
    }
    // Voila!  We've received our entire datagram
    // without need to know the maximum datagram
    // size before runtime.
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-05-24
      • 1970-01-01
      • 1970-01-01
      • 2017-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多