DatagramChannel发送的本机错误

时间:2014-02-09 08:55:07

标签: java multithreading networking

基本

我有一个应用程序,它使用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 update 45

更多信息

该应用程序正在向DVB-C网络发送SI / EIT数据。我正在为每个80-120个线程创建一个188字节数组的列表,并将其用于使用。线程获取列表并循环遍历列表,直到提供新列表。

  • 错误通常会在多个渠道上同时发生。但它也可能只发生在一个。
  • 错误从未发生过,直到我们有40多个主题。
  • 循环遍历列表时发生错误,而不是在我将新列表绑定到线程时。
  • 应用程序没有耗尽内存。它通常可以为JVM提供高达70%的内存。
  • 奇怪的部分:如果我运行多个app实例,每个处理~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)如果我只需要发送UDP数据包,是否应该使用其他API?我能找到的所有样本都使用DatagramChannel(或更老的替代品)。

3)我仍然坚持这一点。如果有人知道我甚至可以尝试什么,请告诉我。

1 个答案:

答案 0 :(得分:1)

我有完全相同的问题,它是由目标InetSocketAddress中的零端口引起的,当调用 send 方法时。

在您的代码中,目标端口定义为1000 + i,因此它似乎不是问题。无论如何,我会记录抛出异常时使用的目标参数,以防万一。