【问题标题】:Confusion about UDP/IP and sendto/recvfrom return values关于 UDP/IP 和 sendto/recvfrom 返回值的混淆
【发布时间】:2009-04-23 02:03:15
【问题描述】:

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

如果sendtorecvfrom只保证一次发送或接收1个字节,并且可以乱序接收数据报,那么任何UDP协议如何保持一致?这不是意味着当我收到消息中的字节时可以任意打乱它们吗?有没有办法保证一次发送或接收一条消息?

【问题讨论】:

    标签: c++ networking udp


    【解决方案1】:

    比那要强一点。 UDP 确实提供了一个完整的包;缓冲区大小可以任意小,但它必须包含数据包中发送的所有数据。但也有大小限制:如果要发送大量数据,则必须将其分成数据包并自己重新组装。它也不能保证交付,因此您必须检查以确保一切顺利。

    但既然你可以用 UDP 实现所有的 TCP,它必须是可能的。

    通常,您使用 UDP 所做的是制作离散的小数据包。

    打个比方,把 UDP 想象成发送明信片,把 TCP 想象成打电话。当您发送明信片时,您无法保证送达,因此您需要做一些事情,比如回复确认函。通过一个电话,您知道连接存在,并且您会立即听到答案。

    【讨论】:

      【解决方案2】:

      没有。使用 sendto 您可以发送数据包,其中可以包含一个字节。 如果您将 10 个字节作为单个 sendto 调用发送,这 10 个字节将被发送到一个数据包中,这将像您期望的那样被连贯地接收。

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

      这类似于通过邮政服务寄送一本书。您可以将整本书打包到一个盒子中,或者撕下每一页并将每一页作为单独的信件发送。在第一种情况下,包裹比较大,但您收到的书是一个单一的、有序的实体。在后者中,每个包都很轻,但祝你好运;)

      【讨论】:

        【解决方案3】:

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

        【讨论】:

          【解决方案4】:

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

          经过一些实验,我发现至少在 Windows 上,发送一个 UDP 数据包到主机上的一个端口,这可能会导致后续的 recvfrom 得到 0 字节。我怀疑某种拒绝通知可能来自另一端。我现在用它来提醒我,我忘记在服务器上启动用于查找客户端传入流量的进程。

          顺便说一句,如果我改为“发送到”一个有效但未使用的 IP 地址,则选择不会返回就绪状态并按预期阻止。我还发现阻塞与非阻塞套接字没有区别。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-10-10
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-08-02
            • 2020-12-29
            相关资源
            最近更新 更多