【问题标题】:DatagramChannel Send Missing On WireDatagramChannel 在线发送丢失
【发布时间】: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 请求,并发现了问题的原因。我最终回答了我自己的问题。

标签: java udp arp


【解决方案1】:

实际上,我在 Wireshark 中进行了更多的摆弄,最终发现了原因。我无意中过滤掉了 ARP 请求,这似乎是问题的原因,正如this answer 中提到的那样:

ARP 仅对指定目标地址的一个出站 IP 数据报进行排队,同时将该 IP 地址解析为 MAC 地址。如果基于 UDP 的应用程序将多个 IP 数据报发送到单个目标地址而在它们之间没有任何暂停,则如果不存在 ARP 缓存条目,则可能会丢弃一些数据报。应用程序可以通过在发送数据包流之前调用 Iphlpapi.dll 例程 SendArp() 来建立 ARP 缓存条目来弥补这一点。

看来 ARP 条目很快就过时了,偶尔的 ARP 请求会导致数据包丢失。我增加了 PC 上接口的 ARP 超时,现在丢弃的数据包发生的频率要低得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-05-11
    • 2017-01-28
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    • 2018-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多