【发布时间】: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 数据包不是最好的主意。