简体   繁体   English

DatagramChannel发送在线丢失

[英]DatagramChannel Send Missing On Wire

I'm seeing some occasional missing data with a datagram channel in a tool I'm developing. 我正在开发的工具中偶尔会出现数据报通道丢失数据的情况。 UDP is part of the requirement here, so I'm mostly just trying to troubleshoot the behavior I'm seeing. UDP是此处要求的一部分,因此我主要只是在尝试解决所看到的行为。 The tool is being developed with Java 7 (another requirement), but the computer on which I'm seeing the behavior occur is running on a Java 8 JRE. 该工具是使用Java 7开发的(另一个要求),但是我看到其行为发生的计算机是在Java 8 JRE上运行的。

I have a decorator class that decorates a call to DatagramChannel.send with some additional behavior, but the call effectively boils down to this: 我有一个装饰器类,它使用一些其他行为来装饰对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;
    }
}

There is an additional bit of decoration above this that performs our own fragmentation (as part of the requirements of the remote host). 除此之外,还有一点点装饰可以执行我们自己的分段(作为远程主机要求的一部分)。 Thus the source data is always guaranteed to be at most 1000 bytes (well within the limit for an ethernet frame). 因此,始终保证源数据最多为1000个字节(完全在以太网帧的限制内)。 The decorated channel is also configured for blocking I/O. 装饰通道也配置为阻止I / O。

What I'm seeing on rare occasions, is that this routine (and thus the DatagramChannel's send method) will be called, but no data is seen on the wire (which is monitored with Wireshark). 在极少数情况下,我看到的是该例程(以及DatagramChannel的send方法)将被调用,但是在线路上没有看到任何数据(由Wireshark进行监视)。 The send routine always returns the number of bytes that should have been written in this case too (so bytesWritten == bytesToWrite). 在这种情况下,发送例程也总是返回应该写入的字节数(因此,bytesWritten == bytesToWrite)。

I understand that UDP has reliability issues (for which we have our own data reliability mechanism that accounts for data loss and other issues), but I'm curious about the behavior of the Datagram channel's implementation. 我了解UDP存在可靠性问题(为此,我们拥有解决数据丢失和其他问题的数据可靠性机制),但是我对数据报通道实现的行为感到好奇。 If send is returning the number of bytes written, should I not at least see a corresponding frame in Wireshark? 如果send返回的是写入的字节数,我是否应该至少在Wireshark中看不到相应的帧? Otherwise, I would expect the native implementation to possibly throw an exception, or at least not return the number of bytes I expected to write? 否则,我希望本机实现可能引发异常,或者至少不返回我希望写入的字节数?

I actually ended up discovering the cause with more fiddling in Wireshark. 实际上,我最终在Wireshark中发现了更多原因。 I was unintentionally filtering out ARP requests, which seem to be the cause of the problem, as mentioned in this answer : 我无意中过滤掉了ARP请求,这似乎是导致此问题的原因,如以下答案所述

ARP queues only one outbound IP datagram for a specified destination address while that IP address is being resolved to a MAC address. 当该IP地址解析为MAC地址时,ARP仅将一个出站IP数据报排队在指定的目标地址中。 If a UDP-based application sends multiple IP datagrams to a single destination address without any pauses between them, some of the datagrams may be dropped if there is no ARP cache entry already present. 如果基于UDP的应用程序将多个IP数据报发送到单个目标地址而在它们之间没有任何暂停,则如果不存在ARP缓存条目,则某些数据报可能会被丢弃。 An application can compensate for this by calling the Iphlpapi.dll routine SendArp() to establish an ARP cache entry, before sending the stream of packets. 在发送数据包流之前,应用程序可以通过调用Iphlpapi.dll例程SendArp()建立ARP缓存条目来对此进行补偿。

It appears the ARP entries were going stale really quick and the occasional ARP request would cause the dropped packet. 看来ARP条目很快就会过时,偶尔的ARP请求会导致丢包。 I increased the ARP timeout for the interface on the PC and the dropped packet happens much less often now. 我增加了PC上接口的ARP超时,丢弃的数据包现在很少发生了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM