2015-02-17 5 views
1

Я вижу некоторые случайные отсутствующие данные с каналом дейтаграммы в инструменте, который я разрабатываю. UDP является частью требования здесь, поэтому я в основном просто пытаюсь устранить поведение, которое я вижу. Инструмент разрабатывается с помощью Java 7 (другое требование), но компьютер, на котором я вижу поведение, работает на Java 8 JRE.DatagramChannel Отправить отсутствующий провод

У меня есть класс декоратора, который украшает вызов 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 байт (в пределах лимита для Ethernet-фрейма). Декорированный канал также настроен для блокировки ввода-вывода.

То, что я вижу в редких случаях, заключается в том, что эта процедура (и, следовательно, метод отправки DatagramChannel) будет вызываться, но на проводнике (который контролируется Wireshark) не будет видно никаких данных. Процедура отправки всегда возвращает количество байтов, которые также должны были быть написаны в этом случае (так что bytesWritten == bytesToWrite).

Я понимаю, что UDP имеет проблемы с надежностью (для чего у нас есть собственный механизм надежности данных, который учитывает потерю данных и другие проблемы), но мне интересно о поведении реализации канала Datagram. Если send возвращает количество записанных байтов, не должен ли я, по крайней мере, видеть соответствующий кадр в Wireshark? В противном случае я ожидал бы, что встроенная реализация может вызвать исключение или, по крайней мере, не вернуть число байтов, которые я ожидал написать?

+0

Все, что возвращает значение, означает, что данные попали в буфер отправки локального сокета. Пакет может быть сброшен где-нибудь между базовым 'sendto()' и базовым 'recvfrom()' сверстника. – EJP

+0

Да, я смог немного поработать с Wireshark. Я непреднамеренно отфильтровывал ARP-запросы и обнаружил причину проблемы. В итоге я ответил на свой вопрос. –

ответ

1

На самом деле я действительно обнаружил причину с более вопиющим в Wireshark. Я был непреднамеренно отфильтровывая ARP запросы, которые, как представляется, является причиной проблемы, как уже упоминалось в this answer:

ARP очереди только один исходящий IP датаграммы для определенного адреса назначения в то время как IP-адрес разрешается в MAC-адрес. Если приложение на основе UDP отправляет несколько IP-дейтаграмм на один адрес назначения без каких-либо пауз между ними, некоторые из датаграмм могут быть удалены, если уже нет записи ARP-кэша. Приложение может компенсировать это, вызывая процедуру IArlpapi.dll SendArp() для установки записи кэша ARP перед отправкой потока пакетов.

Похоже, что записи ARP выглядели очень быстро, и случайный запрос ARP вызывал упавший пакет. Я увеличил тайм-аут ARP для интерфейса на ПК, и выпавший пакет происходит гораздо реже.