在Node.js中获取本地IP地址

432

我在我的电脑上运行了一个简单的Node.js程序,我想获取运行该程序的PC的本地IP地址。如何使用Node.js获取它?


1
值得思考的是,可以查看 http://joeyh.name/code/moreutils/ 和 https://github.com/polotek/procstreams。我从不离开家门而没有它们。 - Tegra Detra
尝试一下这个:https://github.com/indutny/node-ip - Stephen Last
44个回答

3
var ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress 

谢谢OP询问本地IP地址,但我需要的不是本地IP地址,所以还是谢谢。 - Takis

3
这是之前例子的变体。它会过滤掉 VMware 接口等。如果不传递索引,它会返回所有地址。否则,你可能想将其默认设置为 0,然后只传递 null 来获取全部,但这需要你自己解决。如果愿意添加正则表达式过滤器,也可以传入另一个参数。
function getAddress(idx) {

    var addresses = [],
        interfaces = os.networkInterfaces(),
        name, ifaces, iface;

    for (name in interfaces) {
        if(interfaces.hasOwnProperty(name)){
            ifaces = interfaces[name];
            if(!/(loopback|vmware|internal)/gi.test(name)){
                for (var i = 0; i < ifaces.length; i++) {
                    iface = ifaces[i];
                    if (iface.family === 'IPv4' &&  !iface.internal && iface.address !== '127.0.0.1') {
                        addresses.push(iface.address);
                    }
                }
            }
        }
    }

    // If an index is passed only return it.
    if(idx >= 0)
        return addresses[idx];
    return addresses;
}

3

根据一条评论,以下是当前版本Node.js的工作原理:

var os = require('os');
var _ = require('lodash');

var ip = _.chain(os.networkInterfaces())
  .values()
  .flatten()
  .filter(function(val) {
    return (val.family == 'IPv4' && val.internal == false)
  })
  .pluck('address')
  .first()
  .value();

上面回答中的注释缺少调用 values()。看起来 os.networkInterfaces() 现在返回一个对象而不是一个数组。


1
我喜欢 lodash。特别是 lodash golf!_.chain(..) 可以重写为 _(...).filter(..) 可以重写为 .where({family: 'IPv4', internal: false}),并且当链接时,您可以省略最后的 value(),因为 .first() 会为您执行它。 - Ryan Graham

3
谷歌搜索“Node.js get server IP”后将我引导到这个问题,因此让我们为那些试图在其Node.js服务器程序中实现此功能的人提供替代答案(可能是原始发布者的情况)。
在服务器仅绑定到一个IP地址的最简单情况下,应该不需要确定IP地址,因为我们已经知道将其绑定到了哪个地址(例如传递给listen()函数的第二个参数)。
在服务器绑定到多个IP地址的较不简单的情况下,我们可能需要确定连接到客户端的接口的IP地址。正如Tor Valamo所简要建议的那样,现在我们可以轻松地从连接的套接字及其localAddress属性中获取这些信息。
例如,如果程序是Web服务器:
var http = require("http")

http.createServer(function (req, res) {
    console.log(req.socket.localAddress)
    res.end(req.socket.localAddress)
}).listen(8000)

如果它是一个通用的TCP服务器:

var net = require("net")

net.createServer(function (socket) {
    console.log(socket.localAddress)
    socket.end(socket.localAddress)
}).listen(8000)

运行服务器程序时,此解决方案提供了非常高的可移植性、准确性和效率。

更多详细信息请参见:


3

如果你喜欢简洁明了的东西,可以使用Lodash

var os = require('os');
var _ = require('lodash');
var firstLocalIp = _(os.networkInterfaces()).values().flatten().where({ family: 'IPv4', internal: false }).pluck('address').first();

console.log('First local IPv4 address is ' + firstLocalIp);


3
以下解决方案对我有效。
const ip = Object.values(require("os").networkInterfaces())
        .flat()
        .filter((item) => !item.internal && item.family === "IPv4")
        .find(Boolean).address;

2
非常好。如果找不到,则稍作调整:const ip = Object.values(require("os").networkInterfaces()).flat().reduce((ip, {family, address, internal}) => ip || !internal && family === 'IPv4' && address, ''); - x0a

2

这是对已接受答案的修改,它不考虑vEthernet IP地址,例如Docker等。

/**
 * Get local IP address, while ignoring vEthernet IP addresses (like from Docker, etc.)
 */
let localIP;
var os = require('os');
var ifaces = os.networkInterfaces();
Object.keys(ifaces).forEach(function (ifname) {
   var alias = 0;

   ifaces[ifname].forEach(function (iface) {
      if ('IPv4' !== iface.family || iface.internal !== false) {
         // Skip over internal (i.e. 127.0.0.1) and non-IPv4 addresses
         return;
      }

      if(ifname === 'Ethernet') {
         if (alias >= 1) {
            // This single interface has multiple IPv4 addresses
            // console.log(ifname + ':' + alias, iface.address);
         } else {
            // This interface has only one IPv4 address
            // console.log(ifname, iface.address);
         }
         ++alias;
         localIP = iface.address;
      }
   });
});
console.log(localIP);

这将返回一个IP地址,例如192.168.2.169而不是10.55.1.1


2
打印 undefined - 1252748
它将未定义的值打印到控制台 - Jamviet.com

2
以下是一个允许以可移植的方式获取IPv4和IPv6地址的变体:
/**
 * Collects information about the local IPv4/IPv6 addresses of
 * every network interface on the local computer.
 * Returns an object with the network interface name as the first-level key and
 * "IPv4" or "IPv6" as the second-level key.
 * For example you can use getLocalIPs().eth0.IPv6 to get the IPv6 address
 * (as string) of eth0
 */
getLocalIPs = function () {
    var addrInfo, ifaceDetails, _len;
    var localIPInfo = {};
    //Get the network interfaces
    var networkInterfaces = require('os').networkInterfaces();
    //Iterate over the network interfaces
    for (var ifaceName in networkInterfaces) {
        ifaceDetails = networkInterfaces[ifaceName];
        //Iterate over all interface details
        for (var _i = 0, _len = ifaceDetails.length; _i < _len; _i++) {
            addrInfo = ifaceDetails[_i];
            if (addrInfo.family === 'IPv4') {
                //Extract the IPv4 address
                if (!localIPInfo[ifaceName]) {
                    localIPInfo[ifaceName] = {};
                }
                localIPInfo[ifaceName].IPv4 = addrInfo.address;
            } else if (addrInfo.family === 'IPv6') {
                //Extract the IPv6 address
                if (!localIPInfo[ifaceName]) {
                    localIPInfo[ifaceName] = {};
                }
                localIPInfo[ifaceName].IPv6 = addrInfo.address;
            }
        }
    }
    return localIPInfo;
};

这是同一个函数的CoffeeScript版本:

getLocalIPs = () =>
    ###
    Collects information about the local IPv4/IPv6 addresses of
      every network interface on the local computer.
    Returns an object with the network interface name as the first-level key and
      "IPv4" or "IPv6" as the second-level key.
    For example you can use getLocalIPs().eth0.IPv6 to get the IPv6 address
      (as string) of eth0
    ###
    networkInterfaces = require('os').networkInterfaces();
    localIPInfo = {}
    for ifaceName, ifaceDetails of networkInterfaces
        for addrInfo in ifaceDetails
            if addrInfo.family=='IPv4'
                if !localIPInfo[ifaceName]
                    localIPInfo[ifaceName] = {}
                localIPInfo[ifaceName].IPv4 = addrInfo.address
            else if addrInfo.family=='IPv6'
                if !localIPInfo[ifaceName]
                    localIPInfo[ifaceName] = {}
                localIPInfo[ifaceName].IPv6 = addrInfo.address
    return localIPInfo
console.log(getLocalIPs()) 的示例输出
{ lo: { IPv4: '127.0.0.1', IPv6: '::1' },
  wlan0: { IPv4: '192.168.178.21', IPv6: 'fe80::aa1a:2eee:feba:1c39' },
  tap0: { IPv4: '10.1.1.7', IPv6: 'fe80::ddf1:a9a1:1242:bc9b' } }

2
许多时候,我发现有多个内部和外部接口可用(例如:10.0.75.1172.100.0.1192.168.2.3),而我真正需要的是外部接口(172.100.0.1)。
如果其他人也有类似的问题,下面提供了一种方法,希望能对大家有所帮助...
const address = Object.keys(os.networkInterfaces())
    // flatten interfaces to an array
    .reduce((a, key) => [
        ...a,
        ...os.networkInterfaces()[key]
    ], [])
    // non-internal ipv4 addresses only
    .filter(iface => iface.family === 'IPv4' && !iface.internal)
    // project ipv4 address as a 32-bit number (n)
    .map(iface => ({...iface, n: (d => ((((((+d[0])*256)+(+d[1]))*256)+(+d[2]))*256)+(+d[3]))(iface.address.split('.'))}))
    // set a hi-bit on (n) for reserved addresses so they will sort to the bottom
    .map(iface => iface.address.startsWith('10.') || iface.address.startsWith('192.') ? {...iface, n: Math.pow(2,32) + iface.n} : iface)
    // sort ascending on (n)
    .sort((a, b) => a.n - b.n)
    [0]||{}.address;

2
与其他答案类似,但更为简洁:
'use strict';

const interfaces = require('os').networkInterfaces();

const addresses = Object.keys(interfaces)
  .reduce((results, name) => results.concat(interfaces[name]), [])
  .filter((iface) => iface.family === 'IPv4' && !iface.internal)
  .map((iface) => iface.address);

1
只是想提一下,你可以用 Object.values(interfaces).flat() 替换 Object.keys(interfaces).reduce(...),它们的效果是一样的。 - kimbaudi

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接