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

我有一个简单的Node.js程序在我的机器上运行,我想获得我的程序正在运行的PC的本地IP地址。我如何在Node.js中获得它?

525624 次浏览

您的本地IP地址总是127.0.0.1。

然后是网络IP地址,可以从ifconfig (*nix)或ipconfig (win)中获取。这只在本地网络中有用。

然后是你的外部/公共IP地址,你只能通过某种方式向路由器请求它,或者你可以设置一个外部服务,在收到请求时返回客户端IP地址。还有其他类似的服务,比如whatismyip.com。

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

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


2013年更新:

现在有了一种新的方法。你可以检查连接的套接字对象中名为localAddress的属性,例如net.socket.localAddress。它返回套接字一端的地址。

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


2015年更新:

前面的已经不管用了。

下面是一个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);

调用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);
}
});

此信息可以在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"

我使用的是Node.js 0.6.5:

$ node -v
v0.6.5

我是这样做的:

var util = require('util');
var exec = require('child_process').exec;


function puts(error, stdout, stderr) {
util.puts(stdout);
}


exec("hostname -i", puts);

运行程序来解析结果似乎有点可疑。这是我用的。

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

这将返回您的第一个网络接口本地IP地址。

下面是我获取本地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';
}

你可以通过使用操作系统模块找到你机器的任何IP地址——那就是本地的 to Node.js:

var os = require('os');


var networkInterfaces = os.networkInterfaces();


console.log(networkInterfaces);

你所需要做的就是调用os.networkInterfaces(),你会得到一个容易管理的列表——比按联赛运行ifconfig更容易。

对于那些对简洁感兴趣的人来说,这里有一些“一行话”。不需要不是标准Node.js安装一部分的插件/依赖项:

eth0的公共IPv4、IPv6地址为阵列:

var ips = require('os').networkInterfaces().eth0.map(function(interface) {
return interface.address;
});

eth0的第一个公网IP地址(一般为IPv4):

var ip = require('os').networkInterfaces().eth0[0].address;

下面是jhurliman的回答的多ip地址版本:

function getIPAddresses() {


var ipAddresses = [];


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) {
ipAddresses.push(alias.address);
}
}
}
return ipAddresses;
}

https://github.com/indutny/node-ip < a href = " https://github.com/indutny/node-ip " > < / >

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

下面是一个允许你获取本地IP地址的变体(在Mac和Windows上测试):


var
// Local IP address that we're trying to calculate
address
// Provides a few basic operating-system related utility functions (built-in)
,os = require('os')
// Network interfaces
,ifaces = os.networkInterfaces();




// Iterate over interfaces ...
for (var dev in ifaces) {


// ... and find the one that matches the criteria
var iface = ifaces[dev].filter(function(details) {
return details.family === 'IPv4' && details.internal === false;
});


if(iface.length > 0)
address = iface[0].address;
}


// Print the result
console.log(address); // 10.25.10.147

谷歌在搜索Node.js获取服务器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)

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

详情请参见:

对上面答案的改进,原因如下:

  • 代码应该尽可能地不言自明。

  • 应该避免使用在…………对数组进行枚举。

  • 在…………枚举应该被验证,以确保被枚举的对象包含你正在寻找的属性。由于JavaScript是松散类型的,在…………可以被交给任何任意对象来处理;验证我们正在寻找的属性是否可用更安全。

     var os = require('os'),
    interfaces = os.networkInterfaces(),
    address,
    addresses = [],
    i,
    l,
    interfaceId,
    interfaceArray;
    
    
    for (interfaceId in interfaces) {
    if (interfaces.hasOwnProperty(interfaceId)) {
    interfaceArray = interfaces[interfaceId];
    l = interfaceArray.length;
    
    
    for (i = 0; i < l; i += 1) {
    
    
    address = interfaceArray[i];
    
    
    if (address.family === 'IPv4' && !address.internal) {
    addresses.push(address.address);
    }
    }
    }
    }
    
    
    console.log(addresses);
    

根据注释,以下是当前版本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()现在返回一个对象而不是一个数组。

下面是前面例子的一个变种。它小心过滤掉VMware接口,等等。如果你不传递索引,它会返回所有地址。否则,您可能希望将其默认值设置为0,然后传递null以获取所有值,但您将整理这些。如果想要添加的话,还可以为regex过滤器传入另一个参数。

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;
}

使用:

var os = require('os');
var networkInterfaces = os.networkInterfaces();
var arr = networkInterfaces['Local Area Connection 3']
var ip = arr[1].address;

这是我的变体,允许以可移植的方式获得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' } }

Underscore.jsLodash的正确一行代码是:

var ip = require('underscore')
.chain(require('os').networkInterfaces())
.values()
.flatten()
.find({family: 'IPv4', internal: false})
.value()
.address;

如果你喜欢简洁的东西,这里使用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);

下面是一个简单的JavaScript版本,用于获取单个IP地址:

function getServerIp() {


var os = require('os');
var ifaces = os.networkInterfaces();
var values = Object.keys(ifaces).map(function(name) {
return ifaces[name];
});
values = [].concat.apply([], values).filter(function(val){
return val.family == 'IPv4' && val.internal == false;
});


return values.length ? values[0].address : '0.0.0.0';
}

对于Linux和macOS,如果你想通过同步方式获取你的IP地址,试试这个:

var ips = require('child_process').execSync("ifconfig | grep inet | grep -v inet6 | awk '{gsub(/addr:/,\"\");print $2}'").toString().trim().split("\n");
console.log(ips);

结果会是这样的:

['192.168.3.2', '192.168.2.1']

更大的问题是“为什么?”

如果你需要知道Node.js实例正在监听的服务器,你可以使用req.hostname

公认的答案是异步的。我想要一个同步版本:

var os = require('os');
var ifaces = os.networkInterfaces();


console.log(JSON.stringify(ifaces, null, 4));


for (var iface in ifaces) {
var iface = ifaces[iface];
for (var alias in iface) {
var alias = iface[alias];


console.log(JSON.stringify(alias, null, 4));


if ('IPv4' !== alias.family || alias.internal !== false) {
debug("skip over internal (i.e. 127.0.0.1) and non-IPv4 addresses");
continue;
}
console.log("Found IP address: " + alias.address);
return alias.address;
}
}
return false;

类似于其他答案,但更简洁:

'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);

使用npm ip模块:

var ip = require('ip');


console.log(ip.address());


> '192.168.0.117'

我写了一个node . js模块,通过查看包含默认网关的网络接口来确定您的本地IP地址。

这比从os.networkInterfaces()或DNS主机名查找中选择接口更可靠。它可以忽略VMware虚拟接口、环回接口和VPN接口,它可以在Windows、Linux、Mac OS和FreeBSD上工作。在底层,它执行route.exenetstat并解析输出。

var localIpV4Address = require("local-ipv4-address");


localIpV4Address().then(function(ipAddress){
console.log("My IP address is " + ipAddress);
// My IP address is 10.4.4.137
});

一行程序只用于macOS的第一个本地主机地址。

当在macOS上开发应用程序时,你想在手机上测试它,并且需要你的应用程序自动选择本地主机IP地址。

require('os').networkInterfaces().en0.find(elm => elm.family=='IPv4').address

这只是提到如何自动找到ip地址。 要测试这个,你可以去终端点击

node
os.networkInterfaces().en0.find(elm => elm.family=='IPv4').address

输出将是您的本地主机IP地址。

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

npm install ip

然后使用下面的代码:

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

这里有一个简洁的小命令行,它实现了这个功能:

const ni = require('os').networkInterfaces();
Object
.keys(ni)
.map(interf =>
ni[interf].map(o => !o.internal && o.family === 'IPv4' && o.address))
.reduce((a, b) => a.concat(b))
.filter(o => o)
[0];

这是对已接受答案的修改,它不考虑vEthernet IP地址,如码头工人等。

/**
* 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);

这将返回一个类似192.168.2.169的IP地址,而不是10.55.1.1

很多时候,我发现有多个内部和外部面向接口可用(例如: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;

如果你不想安装依赖,并且正在运行*nix系统,你可以这样做:

hostname -I

你会得到主机的所有地址,你可以在node中使用这个字符串:

const exec = require('child_process').exec;
let cmd = "hostname -I";
exec(cmd, function(error, stdout, stderr)
{
console.log(stdout + error + stderr);
});

是一行代码,你不需要像'os'或'node-ip'这样可能会意外增加代码复杂性的其他库。

hostname -h

也是你的朋友;-)

希望能有所帮助!

我所知道的是,我想要以192.168.开头的IP地址。这段代码会给你:

function getLocalIp() {
const os = require('os');


for(let addresses of Object.values(os.networkInterfaces())) {
for(let add of addresses) {
if(add.address.startsWith('192.168.')) {
return add.address;
}
}
}
}

当然,如果你想要一个不同的数字,你可以改变数字。

我只用Node.js就能做到这一点。

node . js:

var os = require( 'os' );
var networkInterfaces = Object.values(os.networkInterfaces())
.reduce((r,a) => {
r = r.concat(a)
return r;
}, [])
.filter(({family, address}) => {
return family.toLowerCase().indexOf('v4') >= 0 &&
address !== '127.0.0.1'
})
.map(({address}) => address);
var ipAddresses = networkInterfaces.join(', ')
console.log(ipAddresses);

作为Bash脚本(需要安装Node.js)

function ifconfig2 ()
{
node -e """
var os = require( 'os' );
var networkInterfaces = Object.values(os.networkInterfaces())
.reduce((r,a)=>{
r = r.concat(a)
return r;
}, [])
.filter(({family, address}) => {
return family.toLowerCase().indexOf('v4') >= 0 &&
address !== '127.0.0.1'
})
.map(({address}) => address);
var ipAddresses = networkInterfaces.join(', ')
console.log(ipAddresses);
"""
}

这可能是最干净、最简单的答案,没有依赖关系。这适用于所有平台。

const { lookup } = require('dns').promises;
const { hostname } = require('os');


async function getMyIPAddress(options) {
return (await lookup(hostname(), options))
.address;
}

使用内部ip:

const internalIp = require("internal-ip")


console.log(internalIp.v4.sync())

下面的解决方案对我来说是可行的

const ip = Object.values(require("os").networkInterfaces())
.flat()
.filter((item) => !item.internal && item.family === "IPv4")
.find(Boolean).address;

我可能在这个问题上迟到了,但如果有人想要一个一行ES6解决方案来获得IP地址数组,那么这应该会帮助你:

Object.values(require("os").networkInterfaces())
.flat()
.filter(({ family, internal }) => family === "IPv4" && !internal)
.map(({ address }) => address)

作为

Object.values(require("os").networkInterfaces())

将返回一个数组的数组,所以flat()被用来将它平展为一个数组

.filter(({ family, internal }) => family === "IPv4" && !internal)

将过滤数组只包括IPv4地址,如果它不是内部

最后

.map(({ address }) => address)

是否只返回过滤数组的IPv4地址

因此结果将是[ '192.168.xx.xx' ]

然后,如果您想要或更改筛选条件,您可以获得该数组的第一个索引

OS使用的是Windows

var ip = req.headers['x-forwarded-for'] || req.socket.remoteAddress
这里的一些答案对我来说似乎不必要地过于复杂。 这里有一个更好的方法,使用普通的Nodejs
import os from "os";


const machine = os.networkInterfaces()["Ethernet"].map(item => item.family==="IPv4")


console.log(machine.address) //gives 192.168.x.x or whatever your local address is

参见文档:NodeJS - os模块:networkInterfaces