基本本地錯誤發送
我有一個是在發送多個線程使用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位)
- 64位的Java 7更新45
更多信息
的應用正在發送SI/EIT數據到DVB-C網絡。我爲每個80-120個線程創建一個188字節的數組列表並給它使用。線程獲取列表並循環遍歷列表,直到提供新列表。
- 該錯誤通常發生在多個通道上。但它也可能發生在一個人身上。
- 直到我們有40多個線程時,纔會發生錯誤。
- 循環遍歷列表時發生錯誤,而不是當我將新列表綁定到線程時。
- 該應用程序沒有用完內存。它通常運行高達JVM內存的70%。
- 奇怪的部分:如果我運行多個應用程序的每個實例〜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)我仍然堅持這一點。如果任何人有一個想法,我甚至可以嘗試,請讓我知道。
爲什麼你在沒有進行任何連接時設置多播屬性? – EJP
你可以試試MulticastSocket。你不應該像這樣使用非阻塞模式。在OP_WRITE上選擇,而不是睡覺。 – EJP