【问题标题】:UDP recvfrom queryUDP recvfrom 查询
【发布时间】:2016-01-09 04:21:39
【问题描述】:
int recvfrom(SOCKET            socket, 
             char            * buffer, 
             int               buflen, 
             int               flags, 
             struct sockaddr * from, 
             int             * fromlen);

我知道recvfrom() 在从套接字读取buflen 后立即返回。我的问题是 -

  1. 如果我请求buflen of 2000 并且套接字队列中的单个数据包大小为 2400,该怎么办?

  2. 如果我请求了 2000 的 buflen 并且套接字队列中的单个数据包大小为 1400,该怎么办?

  3. 以上问题的答案是否对 TCP 和 UDP 都适用?如果不是,有什么区别。

提前感谢回复。

【问题讨论】:

    标签: c sockets tcp udp recvfrom


    【解决方案1】:

    首先,recvfrom() 仅在已经有内容等待读取或套接字处于非阻塞模式时立即返回。否则,它会等待数据到达。

    其次,UDP 是孤注一掷。与 TCP 对流数据进行操作不同,UDP 以数据报的形式进行操作,数据报不能分段读取。

    所以,回答你的问题:

    1. 2000 字节将被复制到您的缓冲区中,剩余的 400 字节被丢弃并丢失,因为您的缓冲区太小而无法接收完整的数据报。 recvfrom() 会报 EMSGSIZE 错误。

    2. 您的缓冲区足够大,可以接收完整的数据报,因此 1400 字节将被复制到您的缓冲区中。 recvfrom() 会报告成功。

    3. 这些不适用于 TCP。首先,您通常不会将recvfrom() 与 TCP 一起使用,而是使用recv()。但在任何一种情况下,在 TCP 中,recv/from() 接收当时当前可用的任何字节,如果需要,阻塞,最多指定字节数,但可能更少。您可以继续调用recv/from() 来接收剩余的字节,因为 TCP 是基于流的。由于 UDP 是基于消息的,因此您无法接收剩余的字节,它们会丢失。下一个recv/from() 将读取下一个可用的数据报。

    【讨论】:

    • 回复第一个答案,截断你的意思是我将能够通过下一次 recvfrom 调用获得剩余字节?
    • @Coder 你会失去剩下的。只需为 UDP 使用 64k 缓冲区。
    • @Coder:在 TCP 中,是的。在 UDP 中,没有。
    • @Coder:详细说明 Stas 的评论,64k 是 UDP 数据报的最大大小,因此如果您使用 64k 缓冲区进行读取,那么您将永远不会截断数据报。
    • @Coder:UDP 数据包头使用 16 位无符号整数作为有效负载大小,因此recvfrom() 在 UDP 中一次读取的字节数永远不会超过 65535 个。
    【解决方案2】:

    recvfrom() 从套接字读取最多 buflen。它可以读取更少,这就是为什么您应该始终检查返回值。

    1) 它会将 2000 字节复制到您的缓冲区中。对于 UDP,多余的数据将丢失。对于 TCP,您应该能够通过再次调用 recvfrom() 来接收它。

    2) 它将 1400 字节复制到您的缓冲区中。

    3) 一般recvfrom()用于UDP,recv()用于TCP,除此之外其他行为同上。

    【讨论】:

    • 你的意思是说,recvfrom 在达到请求的 buf 或单个数据包的大小时立即返回?
    • recvfrom 只要有东西要返回就会返回。使用 TCP 还是 UDP 决定了它返回多少以及是否会发生数据丢失。
    • 它将读取当前可用的尽可能多的数据,直到缓冲区的大小。不一定是单个数据包的大小。
    • @Coder for UDP,recvfrom 为您提供 1 个数据包(如果您的缓冲区太小,该数据包可能会被截断,并且该数据包的剩余数据将永远丢失)。它不结合几个数据包的结果。对于 TCP,它是不同的,因为 TCP 是一个流,并且不保留数据包边界 - 一旦接收到任何数据,您就会获得尽可能多的数据,直到您的缓冲区大小。
    • @Colin__s 我不明白,您的评论与您给出的 2) 答案是否矛盾?让我再扩展 2 个问题,假设我在队列中有 2 个数据包,每个 1400 字节,我请求了 2000,根据您的评论,单个 recvfrom 调用将返回 2000 字节(?)1400 第一个数据包 + 600 个下一个数据包?
    猜你喜欢
    • 2023-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-13
    • 2015-06-11
    • 2019-03-24
    • 2020-04-01
    • 1970-01-01
    相关资源
    最近更新 更多