大家好日子!
我正在开发java UDP服务器。我向服务器发送了大量数据,由于收到的缓冲区大小较小,因此丢失了部分传入数据包。现在我以这种方式设置接收缓冲区 -
DatagramChannel serverChannel;
serverChannel.setOption(StandardSocketOptions.SO_RCVBUF, 1024*1024*10); // 10 MB
有意义吗?此代码没有解决数据包丢失的问题。我的操作系统 - 64位Windows 7.
还有一个问题 - 我的网络控制器的接收缓冲区属性默认为512 - 是字节还是兆字节?如果它是512 字节,是否有必要手动增加此属性?我认为以编程方式增加缓冲区实际上会增加操作系统缓冲区,但这没有意义,因为最初udp数据包会“进入”我的网卡。
答案 0 :(得分:3)
我将大量数据发送到我的服务器,由于收到的缓冲区大小很小,因此丢失了部分传入数据包。
你不知道。有很多可能的原因。
现在我正以这种方式设置接收缓冲区 -
DatagramChannel serverChannel;
serverChannel.setOption(StandardSocketOptions.SO_RCVBUF, 1024*1024*10); // 10 MB
有意义吗?
实际上,这是一个巨大的缓冲区,操作系统可能会将其截断为更合理的大小。设置后尝试获取该选项,并查看实际大小。
此代码未解决数据包丢失问题。
没人说会的。你只是假设它。
还有一个问题 - 我的网络控制器的接收缓冲区属性默认为512 - 是字节还是兆字节?
在你告诉我们你正在使用什么网卡之前,没有人可以回答这个问题,但是你应该能够从制造商的数据中发现这一点。
如果它是512字节,是否有必要手动增加该属性?
不仅不必要而且不可能。
我认为以编程方式增加缓冲区实际上会增加操作系统缓冲区
如果您的意思是SO_RCVBUF
控制套接字接收缓冲区大小,那是正确的。
但这没有意义
是的。
然后从那里进入操作系统,并从那里进入IP堆栈,并从那里到UDP堆栈,并从那里到socket接收缓冲区。当大多数路径MTU高达1500字节时,NIC似乎不可能具有512字节缓冲区,但是例如它确实是512k有意义。你可以认为它已经足够了,毕竟它确实有效。因为最初udp数据包“进入”我的网卡。
你的基本假设是有缺陷的。 UDP数据包可能由于各种原因而丢失:它们从未被发送,它们被中间路由器丢弃,它们被分段并且并非所有碎片都被接收到接收器,或者接收器的套接字接收缓冲区已满,这反过来又是可能是因为它太小或接收器无法跟上发送者。仅使用巨大的套接字接收缓冲区只能解决其中一个问题。如果您需要可靠性,请使用TCP,或者通过重试实现ACK或NACK机制。
答案 1 :(得分:1)
有意义吗?
有点儿。但是,您无能为力可以保证UDP数据包不会丢失。 UDP本质上是不可靠的协议。如果您的应用程序无法足够快地从套接字中拉出它们,或者如果出现网络错误,则数据包将丢失。
如果您需要将数据可靠地发送到服务器,您应该使用TCP ...
我的网络控制器的接收缓冲区属性默认为512 - 是字节还是兆字节?
我不知道,但我也不怀疑。它更可能是千字节。
我试图增加控制器的缓冲区大小 - 操作系统说512是最大可能的)
那么,你将无法将其增加到10Mb。
所以,如果没有newtwork错误,我的数据包丢失的唯一情况是我处理它们太慢。
不完全是。由于各种原因,数据包可能会在许多地方丢失/丢失。其中一些是“正常行为”而不是“网络错误”;例如当路由器/网桥/网关拥塞时丢包。
增加缓冲区大小看起来足以解决问题,但令人惊讶的是它失败了。
实际上,这并不奇怪。丢包可能是正常行为;见上文。
可能我应该在一个线程中接收数据包并在另一个线程中处理它们,即使我使用java NIO专门开发“一个线程”服务器。
它可能有助于减少操作系统和网络接口中的数据包丢失。但是,您最终会缓冲应用程序内存中的数据,这可能会导致更糟糕的问题...如果应用程序无法长期跟上。
此外,它不处理因其他原因丢失/丢失的数据包。
最重要的是,您将无法使用UDP实现可靠的无损传输。数据包丢失是不可避免的,你正在浪费时间试图避免它。
您必须设计应用程序以应对丢失的数据报,或者切换到使用TCP或其他提供可靠数据传输的协议。
答案 2 :(得分:1)
UDP发送/接收离散数据包;最大尺寸约为65K。如果要发送的数据多于此数据,则需要将其分成多个数据包。此外,正如其他人所说,UDP是一种不可靠的协议。数据包可能会消失,重复或无序接收。