代码之家  ›  专栏  ›  技术社区  ›  Jay Conrod

对udp/ip和sendto/recvFrom返回值的混淆

  •  2
  • Jay Conrod  · 技术社区  · 15 年前

    我第一次在C++中使用UDP套接字,我不确定我理解它们是如何工作的。我知道 sendto / recvfrom send / recv 通常返回实际发送或接收的字节数。我听说这个值可以任意小(但至少是1),这取决于套接字的缓冲区(读取时)中有多少数据,或者缓冲区(写入时)中还有多少可用空间。

    如果 发送 接收数据 只有保证一次发送或接收1个字节,并且数据报可以无序接收,任何UDP协议如何保持一致?这不意味着消息中的字节在我接收到它们时可以任意地乱序排列吗?有没有一种方法可以保证一条消息同时发送或接收?

    4 回复  |  直到 12 年前
        1
  •  3
  •   Charlie Martin    15 年前

    这是一个 小的 比那更强大。UDP确实提供了一个完整的包;缓冲区大小可以任意小,但它必须包含包中发送的所有数据。但是也有一个大小限制:如果你想发送大量的数据,你必须把它分成包,并且能够自己重新组装它们。这也是没有保证的交付,所以你必须检查,以确保一切都通过。

    但是,由于您可以使用UDP实现所有的TCP,因此它必须是可能的。

    通常,对UDP所做的就是生成离散的小数据包。

    打个比方,想想udp就像发送明信片,tcp就像打电话。当你寄一张明信片时,你不能保证你能收到,所以你需要做一些类似于确认回来的事情。有了一个电话,你就知道连接存在,你马上就能听到答案。

        2
  •  1
  •   Stefano Borini    15 年前

    不。通过send to,您可以发送包,包可以包含一个字节。 如果您将10个字节作为一个sendto调用发送,那么这10个字节将被发送到一个单独的数据包中,该数据包将按照您的期望得到一致的接收。

    当然,如果您决定逐个发送这10个字节,每个字节都有一个send to调用,那么实际上,您发送和接收10个不同的包(每个包包含1个字节),它们可以是任意顺序的。

    它类似于通过邮政服务发送一本书。你可以把这本书作为一个整体打包成一个盒子,或者把每一页撕下来,然后把每一页作为一封单独的信发送出去。在第一种情况下,这个包更大,但你收到的书作为一个单一的,有序的实体。在后者中,每个包装都很轻,但阅读时祝您好运;)

        3
  •  1
  •   Duck    15 年前

    实际上,您可以发送0字节长度的UDP数据报。发送的只是IP和UDP头。另一侧的udp recvFrom()将返回长度为0的值。与TCP不同,这并不意味着对等方关闭了连接,因为使用UDP时没有“连接”。

        4
  •  1
  •   Tom Bates    12 年前

    我有一个客户端程序,它在一个线程中使用阻塞选择(空超时参数),该线程专用于在UDP套接字上等待传入数据。即使它是阻塞的,select有时也会返回一个指示单读描述符“准备好了”。随后的recvFrom返回0。

    经过一些实验,我发现至少在Windows上, 发送 到主机上某个端口的UDP数据包,如果不期望,可能会导致随后的recvFrom获取0字节。我怀疑另一端可能会发出某种拒绝通知。我现在用这个提醒您,我忘记了在服务器上启动查找客户机传入流量的过程。

    顺便说一句,如果我改为“sendto”一个有效但未使用的IP地址,那么select不会按预期返回就绪状态和块。我还发现阻塞和非阻塞套接字没有区别。