Java DatagramChannel SocketException“;无效参数";
我的代码在DatagramChannel中调用send()时抛出SocketException。javadoc甚至没有提到这是可能的。我在某处找到一篇帖子,建议使用IPv4协议栈,使用“-Djava.net.preferIPv4Stack=true”,这没有帮助。我只想发送一个非阻塞DNS请求Java DatagramChannel SocketException“;无效参数";,java,nonblocking,channel,datagram,socketexception,Java,Nonblocking,Channel,Datagram,Socketexception,我的代码在DatagramChannel中调用send()时抛出SocketException。javadoc甚至没有提到这是可能的。我在某处找到一篇帖子,建议使用IPv4协议栈,使用“-Djava.net.preferIPv4Stack=true”,这没有帮助。我只想发送一个非阻塞DNS请求 Exception in thread "main" java.net.SocketException: Invalid argument at sun.nio.ch.DatagramChanne
Exception in thread "main" java.net.SocketException: Invalid argument
at sun.nio.ch.DatagramChannelImpl.send0(Native Method)
at sun.nio.ch.DatagramChannelImpl.sendFromNativeBuffer(DatagramChannelImpl.java:536)
at sun.nio.ch.DatagramChannelImpl.send(DatagramChannelImpl.java:513)
at sun.nio.ch.DatagramChannelImpl.send(DatagramChannelImpl.java:477)
at Test.main(Test.java:31)
以下是相关代码:
public class Test {
private static final byte[] request = hexStringToByteArray("674B010000010000000000000377777706676F6F676C6503636F6D0000010001");
public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
}
return data;
}
public static void main(final String[] args) throws IOException {
String ip = InetAddress.getLocalHost().getHostAddress();
int port = 1024 + (new Random()).nextInt(64507);
DatagramChannel channel = DatagramChannel.open();
channel.configureBlocking(false);
channel.socket().bind(new InetSocketAddress(ip, port));
int sent = channel.send(ByteBuffer.wrap(request), new InetSocketAddress(InetAddress.getByName("8.8.8.8"), 53));
}
}
我认为您的问题在于,通过调用
InetAddress.getLocalHost()
,显式地将客户端的本地套接字绑定到localhost。而不是做:
channel.bind(new InetSocketAddress(ip, port));
您应该实例化InetSocketAddress
,而不指定IP部分。然后,系统将套接字绑定到所有可用接口(0.0.0.0
):
如果您希望明确,也可以这样调用:
channel.bind(new InetSocketAddress("*", port));
这为我解决了问题。基本原理是客户端套接字必须绑定到传出接口,而不是环回。无法复制:我在Linux上的Java 1.8.0上也不例外。@MvG您使用的是什么版本?很抱歉响应太晚,您在我度假时发送了答复,我错过了。你的解决方案奏效了,我没有看到,这让人恼火:)
channel.bind(new InetSocketAddress(port));
channel.bind(new InetSocketAddress("*", port));