如实现NodeJS生成的Java进程中的网络接口的IP地址?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (97)

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] });
提问于
用户回答回答于

这可能有点晚了,但我今天遇到了同样的问题,并进一步调查了一下。

这实际上不是Node.js问题,而是一些奇怪的JVM行为。原始帖子中的解决方法帮助我找到了根本原因:如果您没有'ignore'作为stdio数组中的第一个条目传递,则将使用绑定到文件描述符0(也称为stdin)的unix域套接字生成子进程。

JVM具有检测是否支持IPv6的功能,其中包括以下代码。代码与上面评论中的描述不符。因此,当套接字绑定到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;
    }
}

扫码关注云+社区

领取腾讯云代金券