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) Я все еще придерживаюсь этого. Если у кого есть идея, что я могу попробовать, сообщите мне.
Почему вы устанавливаете свойства многоадресной передачи, когда вы не выполняете никаких соединений? – EJP
Вы можете попробовать MulticastSocket. И вы не должны использовать неблокирующий режим, как это. Вместо сна выберите OP_WRITE. – EJP