由NodeJS发起的Java进程似乎无法检测网络接口的IPv6地址。考虑以下java代码:
public class ListAddresses {
public static void main(String args[]) throws SocketException {
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
for (NetworkInterface netint : Collections.list(nets))
displayInterfaceInformation(netint);
}
static void displayInterfaceInformation(NetworkInterface netint)
throws SocketException {
out.printf("Display name: %s\n", netint.getDisplayName());
out.printf("Name: %s\n", netint.getName());
Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
for (InetAddress inetAddress : Collections.list(inetAddresses)) {
out.printf("InetAddress: %s\n", inetAddress);
}
out.printf("\n");
}
}
如果我从命令行运行它,它将打印以下内容:
Display name: wlan0
Name: wlan0
InetAddress: /fe80:0:0:0:6e88:14ff:fe67:8130%3
InetAddress: /192.168.1.102
Display name: lo
Name: lo
InetAddress: /0:0:0:0:0:0:0:1%1
InetAddress: /127.0.0.1
如果我从NodeJS中启动它,就像这样:
var spawn = require('child_process').spawn;
var prc = spawn('java', ['ListAddresses']);
prc.stdout.on('data', function (data) {
console.log('' + data);
});
然后它的输出是:
Display name:
wlan0
Name: wlan0
InetAddress: /192.168.1.102
Display name: lo
Name: lo
InetAddress: /127.0.0.1
因此缺少IPv6地址。最后,如果我改变这种方式:
var prc = spawn('java', ['ListAddresses'], { stdio: [ 'ignore', null, null] });
然后启动的java进程正确打印所有IP地址(这似乎与https://stackoverflow.com/a/22950304/594406有关,但我不知道如何)。有没有人知道发生了什么?我在1.8.0_66
上使用java v4.2.2
和节点Ubuntu 14.04.3 LTS
。请注意,父NodeJS进程检测到IPv6地址,如果我启动了NodeJS子进程,那么它也会检测到它们。
答案 0 :(得分:2)
这可能有点晚了,但是我今天遇到了同样的问题,并进行了进一步调查。
这实际上不是Node.js问题,而是一些怪异的JVM行为。原始帖子中的解决方法帮助我找到了根本原因:如果您不通过'ignore'
作为stdio
数组中的第一个条目,则将生成带有绑定到file的unix域套接字的子进程。描述符0(又称stdin)。
JVM具有检测是否支持IPv6的功能,其中包括以下piece of code。该代码与上面的注释中的描述不匹配。因此,当套接字绑定到fd 0且其类型不是IPv6套接字时,该实现实际上会禁用IPv6。因此,当Node.js将unix套接字绑定到fd 0时,也会禁用IPv6。
/*
* If fd 0 is a socket it means we've been launched from inetd or
* xinetd. If it's a socket then check the family - if it's an
* IPv4 socket then we need to disable IPv6.
*/
if (getsockname(0, &sa.sa, &sa_len) == 0) {
if (sa.sa.sa_family != AF_INET6) {
close(fd);
return JNI_FALSE;
}
}
我将其报告为Java Bug数据库中的错误,但是由于该代码已经存在了很长时间,因此它可能不是要修复的优先级(或者甚至是故意的?)。
更新:现已确认此问题是错误,现在可以在Java Bug Tracker中看到。