【问题标题】:C++ UDP RecevingC++ UDP 接收
【发布时间】:2020-07-03 12:04:54
【问题描述】:

我有一整天都在努力解决的问题。情况如下:

  1. 我有一个服务器列表 - 比如说 10 个不同的服务器。
  2. 我想使用 sendto 命令向所有 10 台服务器发送提案广播消息。
  3. 然后我想监听并等待 10 个服务器响应 ACK + 一些消息。
  4. 一段时间后,使用来自已响应服务器的数据超时。 (时间会根据请求的数量而变化)

我想利用 UDP 使其独立于连接,但也担心如果我一次发送所有消息,我可能会错过一条消息,因为我没有阻止 revfrom 一直到所有消息都发送完毕。

我可以在每次发送后等待,但从广播的角度来看这似乎效率低下。

我也可以先设置一个监听线程,然后在单独的线程上运行 sendto,但随后监听器(即整个程序)在 main 之外的另一个线程上。

所以我的问题有两个:考虑到我正在尝试做的事情,这些方法中的哪一种(如果有的话)看起来最合适?其次,套接字上是否有任何队列。就像让我们说它不是 10 台,而是 1000 台服务器 - 如果一条消息在它还没有准备好接收时进入,这条消息会被丢弃吗?

我愿意接受有关其他实施方式的建议。

提前致谢!

【问题讨论】:

    标签: c++ network-programming udp


    【解决方案1】:

    如今,大多数个人计算机都位于防火墙后面,可以阻止任何传入的 UDP 数据包 --- 实际上,当今大多数个人计算机也在 NAT 转换层后面,甚至没有自己的 Internet 可路由 IP 地址。在我担心由于时间问题而错过偶尔传入的 UDP 消息之前,我会担心这一点。

    也就是说,如果您的客户端在开放的 Internet 上运行(或者位于配置为允许 UDP 数据包进入的防火墙后面),那么计时问题并不是真正的问题,因为网络堆栈分配了一个作为socket() 调用的一部分,每个套接字的传入数据缓冲区。一旦您在套接字上成功调用了bind(),任何到达该套接字端口的UDP 数据包都将被放入套接字的传入数据缓冲区,准备在下次调用recvfrom() 时移交给您的代码。重要的是,无论您的线程当前是否在 recvfrom() 调用中,都会发生这种缓冲。

    传入数据缓冲区可能会被填满(它的大小是有限的,通常约为 64KB);此时任何额外的传入 UDP 数据包都将被丢弃。避免这种情况的常用方法是确保您尽快调用recvfrom(),或者如果这还不够,您可以使用setsockopt() 告诉网络堆栈使套接字的传入数据缓冲区更大。

    同时,您对sendto() 的调用可能会很快完成,因为只要将数组中的数据复制到套接字的传出数据缓冲区中,sendto() 就会返回。特别是,sendto() 确实等待字节通过网络,或者(通常)甚至等待字节到达您的网卡。在最坏的情况下,它可能会阻塞,直到输出数据缓冲区中有足够的空间来放置数据;并且传出数据缓冲区总是以网络设备的线速耗尽。

    【讨论】:

    • 这非常有用。我进行了 10 秒的测试。之间的延迟,看到所有的消息都通过了。我会记住你的关于防火墙的 cmets。目前,这将是一个本地分布式集群,所以防火墙维护应该不是一个大问题,但它是值得考虑的事情。感谢您对此协议在传输层中的工作方式的澄清和详细说明。
    猜你喜欢
    • 2018-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-18
    • 2020-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多