当接收缓冲区几乎满时,阻止UDP数据包被部分截断

Stopping UDP packets from being partially chopped off when receive buffer is almost full

本文关键字:数据包 UDP 阻止 缓冲区 满时      更新时间:2023-10-16

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

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

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

IP负责处理发送端的碎片,IP数据包最高可达64K,并将按IP进行碎片处理,以适应底层的MTU。

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

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

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