2014-02-09 3 views
0

Basicродные ошибки на DatagramChannel отправить

У меня есть приложение, которое отправляет пакеты с помощью DatagramChannel.send в нескольких потоках каждый на свой собственный IP-адрес/порт, и каждый из них поддержание постоянной скорости передачи/пропускной способности. Каждый сейчас и потом я получаю эту ошибку:

java.net.SocketException: Invalid argument: no further information 
    at sun.nio.ch.DatagramChannelImpl.send0(Native Method) 
    at sun.nio.ch.DatagramChannelImpl.sendFromNativeBuffer(Unknown Source) 
    at sun.nio.ch.DatagramChannelImpl.send(Unknown Source) 
    at sun.nio.ch.DatagramChannelImpl.send(Unknown Source) 
    ... 

Это происходит на случайном - иногда через 5 минут после запуска иногда через день - так что я действительно есть проблемы, воспроизводящие его для тестирования. И на моей домашней машине я не могу воспроизвести ее вообще.

Среды

  • для Windows 7, 8 и Server 2012 (все 64-разрядные)
  • 64bit Java 7 обновление 45

Дополнительная информация

Приложение отправка SI/EIT в сеть DVB-C. Я создаю список 188-байтных массивов для каждого из 80-120 потоков и давая ему возможность использовать. Поток берет список и перебирает список, пока не появится новый список.

  • Ошибка обычно происходит на нескольких каналах одновременно. Но это может произойти и на одном.
  • Ошибка произошла до тех пор, пока у нас не было 40 + потоков.
  • Ошибка происходит при переходе по списку, а не когда я привязываю новый список к потоку.
  • Приложение это не исчерпывает память. Обычно он работает до 70% памяти, предоставленной JVM.
  • Странная часть: если я запускаю несколько экземпляров приложения, каждая обработка ~ 10 проблем одинаковы.

Упрощенный пример кода

for(int i = 0; i < 100; ++i) { 
    final int id = i; 
    new Thread(new Runnable() { 
     @Override 
     public void run() { 
     final Random r = new Random(); 
     final List<byte[]> buffer = Lists.newArrayList(); 
     for(int i = 0; i < 200; ++i) { 
      final byte[] temp = new byte[188]; 
      r.nextBytes(temp); 
      buffer.add(temp); 
     } 

     final SocketAddress target = new InetSocketAddress("230.0.0.18", 1000 + id); 
     try (final DatagramChannel channel = DatagramChannel.open(StandardProtocolFamily.INET)) {        
      channel.configureBlocking(false); 
      channel.setOption(StandardSocketOptions.IP_MULTICAST_IF, NetworkInterface.getByName("eth0"));    
      channel.setOption(StandardSocketOptions.IP_MULTICAST_TTL, 8); 
      channel.setOption(StandardSocketOptions.SO_REUSEADDR, true); 
      channel.setOption(StandardSocketOptions.SO_SNDBUF, 1024 * 64); 

      int counter = 0; 
      int index = 0; 
      while(true) { 
      final byte[] item = buffer.get(index); 
      channel.send(ByteBuffer.wrap(item), target); 
      index = (index + 1) % buffer.size(); 
      counter++; 
      Thread.sleep(1); 
      }    
     } 
     catch(Exception e) { 
      LOG.error("Fail at " + id, e); 
     } 
     } 
    }).start(); 
} 

редактирует:

1) @EJP: Я устанавливаю настройки многоадресных свойства, как фактическое приложение, которое я использую делает объединения (и чтение некоторых данных). Но проблемы сохранялись даже после того, как я их удалил.

2) Должен ли я использовать какой-либо другой API, если мне просто нужно отправить UDP-пакеты? Все образцы, которые я мог найти, используют DatagramChannel (или его более старую альтернативу).

3) Я все еще придерживаюсь этого. Если у кого есть идея, что я могу попробовать, сообщите мне.

+0

Почему вы устанавливаете свойства многоадресной передачи, когда вы не выполняете никаких соединений? – EJP

+0

Вы можете попробовать MulticastSocket. И вы не должны использовать неблокирующий режим, как это. Вместо сна выберите OP_WRITE. – EJP

ответ

1

У меня была точно такая же проблема, и она была вызвана нулевым портом в целевом InetSocketAddress при вызове метода send.

В вашем коде целевой порт определяется как 1000 + i, поэтому это не проблема. Во всяком случае, я бы зарегистрировал целевые параметры, которые используются, когда исключение выбрано, на всякий случай.

+0

Я не нашел ответа на это. Решение состояло в том, чтобы изменить сервер HW, поэтому я подозреваю, что у вас есть неисправность HW или некоторые проблемы с системным/сетевым уровнем. – Ashes

Смежные вопросы