【发布时间】:2015-04-18 14:46:29
【问题描述】:
在我正在开发的工具中,我发现数据报通道偶尔会丢失一些数据。 UDP 是这里要求的一部分,所以我主要只是试图解决我看到的行为。该工具是使用 Java 7 开发的(另一个要求),但我看到该行为发生的计算机正在 Java 8 JRE 上运行。
我有一个装饰器类,它用一些额外的行为装饰对 DatagramChannel.send 的调用,但调用实际上归结为:
public int send( ByteBuffer buffer, SocketAddress target ) throws
{
// some additional decorating code that can't be shared follows
int bytesToWrite = buffer.remaining();
int bytesWritten = decoratedChannel.send(buffer, target);
if (bytesWritten != bytesToWrite) {
// log the occurrence
return bytesWritten;
}
}
在此之上还有一个额外的装饰,它执行我们自己的碎片(作为远程主机要求的一部分)。因此,源数据始终保证最多为 1000 字节(完全在以太网帧的限制范围内)。装饰通道也配置为阻塞 I/O。
我在极少数情况下看到的是,该例程(以及 DatagramChannel 的发送方法)将被调用,但在线路(由 Wireshark 监控)上看不到任何数据。在这种情况下,发送例程也总是返回应该写入的字节数(因此 bytesWritten == bytesToWrite)。
我了解 UDP 存在可靠性问题(我们有自己的数据可靠性机制来解决数据丢失和其他问题),但我对 Datagram 通道的实现行为感到好奇。如果发送返回写入的字节数,我是否应该至少在 Wireshark 中看到相应的帧?否则,我希望本机实现可能会抛出异常,或者至少不返回我期望写入的字节数?
【问题讨论】:
-
返回值告诉你的只是数据进入了本地套接字发送缓冲区。数据包可以在底层
sendto()和对等方的底层recvfrom()之间的任何位置丢弃。 -
是的,我能够使用 Wireshark 进行更多挖掘。我无意中过滤掉了 ARP 请求,并发现了问题的原因。我最终回答了我自己的问题。