在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个回答

570

这些信息可以在os.networkInterfaces()中找到,它是一个对象,将网络接口名称映射到其属性(以便一个接口可以有多个地址):

'use strict';

const { networkInterfaces } = require('os');

const nets = networkInterfaces();
const results = Object.create(null); // Or just '{}', an empty object

for (const name of Object.keys(nets)) {
    for (const net of nets[name]) {
        // Skip over non-IPv4 and internal (i.e. 127.0.0.1) addresses
        // 'IPv4' is in Node <= 17, from 18 it's a number 4 or 6
        const familyV4Value = typeof net.family === 'string' ? 'IPv4' : 4
        if (net.family === familyV4Value && !net.internal) {
            if (!results[name]) {
                results[name] = [];
            }
            results[name].push(net.address);
        }
    }
}
// 'results'
{
  "en0": [
    "192.168.1.101"
  ],
  "eth0": [
    "10.0.0.101"
  ],
  "<network name>": [
    "<ip>",
    "<ip alias>",
    "<ip alias>",
    ...
  ]
}
// results["en0"][0]
"192.168.1.101"

20
var _ = require('underscore'); // 引入Underscore库 var ip = _.chain(require('os').networkInterfaces()) // 调用Node.js内置的os模块获取网络接口信息,并传递给Underscore库进行处理 .flatten() // 将嵌套数组展开为一维数组 .filter(function(val){ return (val.family == 'IPv4' && val.internal == false) }) // 对每个元素过滤,保留符合条件的IPv4地址 .pluck('address') // 从每个元素中提取IPv4地址 .first() // 获取第一个IPv4地址 .value(); // 提取结果并赋值给变量ip console.log(ip) // 输出ip变量的值 - Carter Cole
4
在执行flatten之前,您需要额外调用.values()。 - Guido
5
如果我只想获取当前活动接口的IP地址,该怎么办? - Tejas
25
在Node.js版本大于等于7.0.0的环境中,无需使用Lodash库,可以使用以下一行代码获取所有非内部IPv4地址: Object.values(require('os').networkInterfaces()).reduce((r, list) => r.concat(list.reduce((rr, i) => rr.concat(i.family==='IPv4' && !i.internal && i.address || []), [])), []) - som
21
"Underscore" 翻译为“下划线”,"lowdash" 翻译为“低横线”,"one liner" 翻译为“一行代码”,“gross”翻译有两种不同的意思,如果指恶心或令人讨厌,可翻译为“令人恶心的”或“讨厌的”;如果指144个,可翻译为“一打”。 - B T
显示剩余11条评论

254

这是我使用的。

require('dns').lookup(require('os').hostname(), function (err, add, fam) {
  console.log('addr: ' + add);
})

这应该返回你的第一个网络接口的本地IP地址。


5
@HermannIngjaldsson:这并不是一份非常详尽的批评。你能不能更具体一些?或许可以将示例代码放入一个新问题中,提供更多细节,并问为什么它不能运行? - Xedecimal
14
仅使用 DNS 查询并不总是一个好主意,因为它可能会返回错误的信息(即缓存数据)。在我看来,使用 'os.networkInterfaces' 更好。 - Guido
4
如果您的服务器在某个地方有 DNS 条目,那么使用 DNS 是可行的。然而,在很多应用程序中没有 DNS 条目(例如我的笔记本电脑)。os.networkInterfaces() 可能是一个不错的选择。 - Jeff Whiting
2
请注意,这里使用的是操作系统查找功能,它不一定执行 DNS 查找,并且应该知道自己的主 IP 地址... - w00t
@Offirmo,我已经获取了我的本地网络IP地址,例如192.168.0.101。 - vovchisko
显示剩余7条评论

241

2
这个软件包的文档不够清晰...我能否获取广播地址,还是必须自己提供? - Michael
23
@ majidarif 我不认为这是文档不完善的有效借口。 - Michael
9
这个非常有效。获取IP地址只需要一行代码。太棒了。 - EvSunWoodard
7
它不能提供所有适配器的IP地址。如果您已安装Docker,则它会给出vEthernet Docker地址,而不是您实际的以太网地址。 - TetraDev
1
这个模块有416行代码和10Kb的大小,仅仅是为了获取一个IP地址... 太过冗余了。 - Ryan Wheale
显示剩余7条评论

77

你可以使用 os 模块来查找你的机器的任何IP地址 - 而且它是 Node.js 的 原生 模块:


var os = require('os');

var networkInterfaces = os.networkInterfaces();

console.log(networkInterfaces);

你只需要调用os.networkInterfaces()函数,就可以得到一个易于管理的列表 - 比运行ifconfig更加容易。


11
非常棒的回答。var ip = networkInterfaces ['eth0'] [0] ['address']。(翻译注释:该代码行使用Node.js语言中的networkInterfaces API获取以太网接口eth0的第一个IP地址并将其赋值给变量ip) - Natus Drew
虽然这看起来很不错,因为它很简单,但它的实际效果可能取决于您的网络配置。例如,在 OS X 的默认配置中没有 eth0,而是 en0。 - ccnokes
3
对我来说可以。var address = networkInterfaces ['venet0:0'] [0] .address - Anthony
1
在SunOS 5.11上,这个调用返回一个空对象,感觉很奇怪。 - Michael
这真的是最好的答案。os.networkInterfaces()返回一个简单的JSON对象,方便使用 ;) - chankruze

44

这是我用于获取本地IP地址的实用方法,假设您正在寻找IPv4地址并且机器只有一个真实的网络接口。它可以轻松地重构为返回多接口机器的IP地址数组。

function getIPAddress() {
  var interfaces = require('os').networkInterfaces();
  for (var devName in interfaces) {
    var iface = interfaces[devName];

    for (var i = 0; i < iface.length; i++) {
      var alias = iface[i];
      if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal)
        return alias.address;
    }
  }
  return '0.0.0.0';
}

咖啡版本:getLocalIP = (interfaceName = "en0",version = "IPv4")-> iface = require('os').networkInterfaces()[interfaceName] for alias in iface if (alias.family == version && !alias.internal) return alias.address return "0.0.0.0" - Jay

42

安装一个名为ip的模块,例如:

npm install ip

然后使用这段代码:

var ip = require("ip");
console.log(ip.address());

11
这将返回 127.0.0.1。 - WeSam Abdallah
它返回的是私有IP地址而不是公共IP地址。 - Mehmet Kurtipek
如何显示正在使用的端口? - Benjamin RD
@MrMins,对于TCP连接,<socket>.localPort<socket.remotePort>的含义请参考https://nodejs.org/api/net.html#net_class_net_socket。 - nomad
它返回 DockerNAT IP。 - Michal Miky Jankovský

41

使用npm ip 模块:

var ip = require('ip');

console.log(ip.address());

> '192.168.0.117'

10
我不知道如何告诉现在来到这个页面的用户,这是当前情境下唯一合适的选项。 - Gagan
感谢 @Gagan 您的赞赏。 - KARTHIKEYAN.A
1
是的,那就是它。 - yeahdixon

34
以下是 Node.js 代码片段,它将解析 ifconfig 的输出,并(异步地)返回找到的第一个 IP 地址:
(该代码已在 Mac OS X v10.6(Snow Leopard)上测试过;希望在 Linux 上也能运行。)
var getNetworkIP = (function () {
    var ignoreRE = /^(127\.0\.0\.1|::1|fe80(:1)?::1(%.*)?)$/i;

    var exec = require('child_process').exec;
    var cached;
    var command;
    var filterRE;

    switch (process.platform) {
        // TODO: implement for OSes without the ifconfig command
        case 'darwin':
             command = 'ifconfig';
             filterRE = /\binet\s+([^\s]+)/g;
             // filterRE = /\binet6\s+([^\s]+)/g; // IPv6
             break;
        default:
             command = 'ifconfig';
             filterRE = /\binet\b[^:]+:\s*([^\s]+)/g;
             // filterRE = /\binet6[^:]+:\s*([^\s]+)/g; // IPv6
             break;
    }

    return function (callback, bypassCache) {
        // Get cached value
        if (cached && !bypassCache) {
            callback(null, cached);
            return;
        }

        // System call
        exec(command, function (error, stdout, sterr) {
            var ips = [];
            // Extract IP addresses
            var matches = stdout.match(filterRE);

            // JavaScript doesn't have any lookbehind regular expressions, so we need a trick
            for (var i = 0; i < matches.length; i++) {
                ips.push(matches[i].replace(filterRE, '$1'));
            }

            // Filter BS
            for (var i = 0, l = ips.length; i < l; i++) {
                if (!ignoreRE.test(ips[i])) {
                    //if (!error) {
                        cached = ips[i];
                    //}
                    callback(error, ips[i]);
                    return;
                }
            }
            // Nothing found
            callback(error, null);
        });
    };
})();

使用示例:

getNetworkIP(function (error, ip) {
    console.log(ip);
    if (error) {
        console.log('error:', error);
    }
}, false);

如果第二个参数为true,则函数将每次执行系统调用;否则使用缓存值。


更新版本

返回所有本地网络地址的数组。

已在Ubuntu 11.04(Natty Narwhal)和Windows XP 32上进行测试。

var getNetworkIPs = (function () {
    var ignoreRE = /^(127\.0\.0\.1|::1|fe80(:1)?::1(%.*)?)$/i;

    var exec = require('child_process').exec;
    var cached;
    var command;
    var filterRE;

    switch (process.platform) {
        case 'win32':
        //case 'win64': // TODO: test
            command = 'ipconfig';
            filterRE = /\bIPv[46][^:\r\n]+:\s*([^\s]+)/g;
            break;
        case 'darwin':
            command = 'ifconfig';
            filterRE = /\binet\s+([^\s]+)/g;
            // filterRE = /\binet6\s+([^\s]+)/g; // IPv6
            break;
        default:
            command = 'ifconfig';
            filterRE = /\binet\b[^:]+:\s*([^\s]+)/g;
            // filterRE = /\binet6[^:]+:\s*([^\s]+)/g; // IPv6
            break;
    }

    return function (callback, bypassCache) {
        if (cached && !bypassCache) {
            callback(null, cached);
            return;
        }

        // System call
        exec(command, function (error, stdout, sterr) {
            cached = [];
            var ip;
            var matches = stdout.match(filterRE) || [];
            //if (!error) {
            for (var i = 0; i < matches.length; i++) {
                ip = matches[i].replace(filterRE, '$1')
                if (!ignoreRE.test(ip)) {
                    cached.push(ip);
                }
            }
            //}
            callback(error, cached);
        });
    };
})();

更新版本的使用示例

getNetworkIPs(function (error, ip) {
console.log(ip);
if (error) {
    console.log('error:', error);
}
}, false);

刚刚在OSX Lion上测试过,完美。非常感谢! - T3db0t
我不得不在你的Windows正则表达式中删除单词“IP”后面的连字符,因为我的输出没有连字符(我使用的是32位Windows XP)。我不知道那是打字错误还是你的Windows版本真的在“IP”后面输出了连字符,但为了安全起见,我认为它可以是可选的:filterRE = /\bIP-?[^:\r\n]+:\s*([^\s]+)/g;。除此之外,这个脚本非常棒,真的帮了我大忙。非常感谢! - User not found
@jSepia:这可能是本地化的问题。德语的Windows会打印“IP-Adresse” ;) - user123444555621
现在已经有os.networkInterfaces()了,没有必要使用这样的黑客手段。 - Brad
当语言本身集成了特定的解决方案并为其使用而设计时,将控制台命令输出传输到管道中并不理想。 - trevorKirkby
显示剩余2条评论

24

调用ifconfig非常依赖于平台,并且网络层知道套接字上的IP地址,因此最好是询问它。

Node.js没有直接的方法来执行此操作,但可以打开任何套接字,并询问正在使用的本地IP地址。例如,打开到 www.google.com 的套接字:

var net = require('net');
function getNetworkIP(callback) {
  var socket = net.createConnection(80, 'www.google.com');
  socket.on('connect', function() {
    callback(undefined, socket.address().address);
    socket.end();
  });
  socket.on('error', function(e) {
    callback(e, 'error');
  });
}

使用案例:

getNetworkIP(function (error, ip) {
    console.log(ip);
    if (error) {
        console.log('error:', error);
    }
});

如果你在想,这并不一定获取到世界所看到的公共IP地址。 - artur
如果这个解决方案不需要依赖于互联网连接和连接速度,那将会是一个很好的解决方案。 - Jacob Rask
在我的情况下,这个解决方案非常完美,因为我需要知道特定请求所使用的接口的IP地址。 - radicand
这是唯一可靠地获取本地IP地址的方法,无需用户指定接口名称,谢谢! - Sv443

19

你的本地IP地址始终是127.0.0.1。

然后是网络IP地址,你可以通过ifconfig(*nix)或者ipconfig(win)获取,这只在局域网内有用。

接下来是你的外部/公共IP地址,只有当你能够询问路由器获取它,或设置一个外部服务来返回客户端IP地址时才有用。此外还存在其他类似的服务,如whatismyip.com。

在某些情况下(例如,如果你有WAN连接),网络IP地址和公共IP地址是相同的,都可以用于从外部访问你的计算机。

如果你的网络和公共IP地址不同,你可能需要让你的网络路由器将所有传入的连接转发到你的网络IP地址。


更新2013:

现在有一种新的方法。你可以检查连接的socket对象是否有一个叫做localAddress的属性,例如net.socket.localAddress。它返回socket的本地地址。

最简单的方法是只需打开一个随机端口并侦听它,然后获取你的地址并关闭该套接字。


更新2015:

以前的方法已经不再适用了。


这是否意味着在Node.js中获取网络地址需要调用系统命令ifconfigipconfig并解析响应字符串? - user123444555621
@Pumbaa80 - 基本上,除非你的网络卡有一些可以调用的驱动程序。此外,如果你有多个网络卡(或适配器,如 Hamachi),就没有办法仅调用某种函数并获取一个“主”IP。因此,解析并解释ifconfig的输出几乎是唯一的方法。 - Tor Valamo
看起来 net.socket 在2015年以后返回了undefined,所以“新的做法”不再有效。存在一个net.Socket,但它没有一个localAddress属性。 - trysis

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