【问题标题】:Stopping UDP packets from being partially chopped off when receive buffer is almost full当接收缓冲区快满时阻止 UDP 数据包被部分截断
【发布时间】:2015-04-30 05:29:08
【问题描述】:

我正在努力在 C++ 中实现滑动窗口协议以进行分配。我正在使用 UDP (SOCK_DGRAM) 套接字。有时,程序必须背靠背发送大量数据包(与窗口大小一样大)。到目前为止,我还没有将窗口大小增加到 30 以上,但最终应该可以达到 256。数据包大小必须取自用户输入,因此它可以是任何合理的值。当数据包大小较小时,如 512 字节,则没有问题。当数据包大小较大时,如 40KB,前几个数据包被正确读取,然后我的 readNBytes() 函数在仅读取部分数据后突然挂在其中一个数据包上。我假设操作系统的接收缓冲区正在被填满,并且其中一个数据包的那一部分被丢弃了。进入缓冲区的部分被读取,然后 readNBytes() 正在等待其余部分,这些部分被操作系统丢弃。

发生这种情况时,操作系统是否设置了任何标志供我阅读?理想情况下,如果它不适合接收缓冲区,我想强制操作系统丢弃整个数据包,而不是仅仅参与其中。我的系统上没有定义 IP_DONTFRAG,所以我不知道该怎么做。我还想找到一种方法,使接收缓冲区大小成为我的数据包大小的倍数,这样数据包就不能部分放入缓冲区。克服这个问题的最佳方法是什么?

【问题讨论】:

  • IP 数据包的最大大小通常约为 1500 字节。使用最高可达 9K 或 10K 的巨型帧。所以 512 字节的数据包大小并不小,40K 的数据包大小是闻所未闻的——至少现在是这样。
  • @CraigS.Anderson 我认为最大 IP 数据包大小约为 65K
  • IP 数据包的绝对大小限制为 64K。在实践中,没有巨型帧的限制是 1.5K 或有巨型帧的大约 9K。请记住,IP 数据包需要适合以太网、802.11x、令牌环等帧。
  • 操作系统不会将半个数据包传递给应用程序。在发送端处理分段是 IP 的责任,IP 数据包可以达到 64K,并且将由 IP 分段以适应底层的 MTU。在接收端发生相反的情况,重新组装。使用 UDP,您要么收到整个数据包,要么什么也没有。只接收其中一部分的唯一原因可能是您的应用程序接收缓冲区很小。一些套接字实现将其删除,即使所有内容都已收到。
  • @PhilipStuyck - 由于主机可以丢弃大于 576 (v4) 或 1500 (v6) 字节的碎片数据包,因此发送 64k 数据包不是最好的主意。

标签: c++ sockets udp buffering


【解决方案1】:

操作系统不会将半个数据包传递给应用程序。

在发送端处理分段是 IP 的责任,IP 数据包可以达到 64K,并且将由 IP 分段以适应底层的 MTU。

在接收端发生相反的情况,重新组装。使用 UDP,您要么收到整个数据包,要么什么也没有。 只接收其中一部分的唯一原因可能是您的应用程序接收缓冲区很小。一些套接字实现将其删除,即使所有内容都已收到

【讨论】:

  • 问题出在我的 readNBytes 和 writeNBytes 函数中。几个月来我一直在使用基于连接的套接字,忘记了它们会分解数据块并在另一端重新组合它们。每个片段都作为数据报单独发送,当缓冲区填满时,有些片段会丢失。这个答案通过向我展示我不需要担心的内容,帮助我找到了这个错误。
【解决方案2】:

如果您的recv() 缓冲区对于数据报来说太小,它将被截断。不会造成阻塞。

您的数据报太大了。 IPv4 限制为 65507 字节,但普遍接受的实际限制为 534 字节。您当然应该致力于将它们保持在路径 MTU 下,否则您将保证碎片化,这只会增加数据报丢失的机会。

【讨论】:

    猜你喜欢
    • 2014-12-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多