检查NodeJ中的Internet连接

Don*_*rek 31 networking node.js raspberry-pi

在Raspberry Pi上安装了NodeJS,有没有办法检查rPi是否通过NodeJ连接到互联网?

Jar*_*uba 41

虽然robertklep的解决方案有效,但它远不是最佳选择.dns.resolve超时大约需要3分钟,如果您没有互联网连接则会出错,而dns.lookup几乎可以立即响应错误ENOTFOUND.

所以我做了这个功能:

function checkInternet(cb) {
    require('dns').lookup('google.com',function(err) {
        if (err && err.code == "ENOTFOUND") {
            cb(false);
        } else {
            cb(true);
        }
    })
}

// example usage:
checkInternet(function(isConnected) {
    if (isConnected) {
        // connected to the internet
    } else {
        // not connected to the internet
    }
});
Run Code Online (Sandbox Code Playgroud)

这是迄今为止检查互联网连接的最快方法,它避免了与互联网连接无关的所有错误.

  • 小心那个解决方案!这是我们选择在我们的Electron应用程序中检查连接性的一个,它最终会带来非常糟糕的惊喜.`dns.lookup`在libuv的threadpool上运行.因此,例如,如果您通过`setInterval`运行`checkInternet`(即监视连接),则可能会溢出线程池.**其中一个结果是阻止了应用程序中的所有IO**(因为所有fs操作也在libuv的线程池上运行).一个很好的解释[这里](https://www.future-processing.pl/blog/on-problems-with-threads-in-node-js/) (8认同)
  • dns.lookup() 使用操作系统的 DNS 工具来缓存结果,而 dns.resolve() 只是直接解析主机名。 (4认同)
  • 不幸的是,这个答案是不正确的。我猜想是 DNS 缓存之类的东西导致这个解决方案根本不起作用。即使我已断开与互联网的连接,它也会显示“true”。 (3认同)

rob*_*lep 31

一种快速而肮脏的方法是检查Node是否可以解决www.google.com:

require('dns').resolve('www.google.com', function(err) {
  if (err) {
     console.log("No connection");
  } else {
     console.log("Connected");
  }
});
Run Code Online (Sandbox Code Playgroud)

这并非完全万无一失,因为您的RaspPi可以连接到Internet但由于www.google.com某种原因无法解决,您可能还需要检查err.type以区分"无法解析"和"无法连接到名称服务器,因此连接可能落下').

  • 对于连接,我会选择 google dns 服务器,因此您不依赖于解析 google 的 isp dns,这可能会或可能不会被阻止。李 8.8.8.8 (3认同)
  • @Deep如果你有自己的网站,请尝试解决它而不是谷歌.否则,谷歌等高可用性服务器是您的最佳选择.https://github.com/sindresorhus/is-online是一个选项 (2认同)

Kri*_*sen 9

我不得不在不久前在NodeJS-app中构建类似的东西.我这样做的方法是首先使用networkInterfaces()函数是OS模块,然后检查一个或多个接口是否具有非内部IP.

如果这是真的,那么我使用exec()开始ping一个定义明确的服务器(我喜欢谷歌的DNS服务器).通过检查exec()的返回值,我知道ping是否成功.我根据接口类型调整了ping的数量.分叉流程会带来一些开销,但由于此测试在我的应用程序中执行不太频繁,我可以负担得起.此外,通过使用ping和IP地址,您不依赖于配置DNS.这是一个例子:

var exec = require('child_process').exec, child;
child = exec('ping -c 1 128.39.36.96', function(error, stdout, stderr){
     if(error !== null)
          console.log("Not available")
      else
          console.log("Available")
});
Run Code Online (Sandbox Code Playgroud)


chi*_*ens 7

这是一个单行:(节点 10.6+)

let isConnected = !!await require('dns').promises.resolve('google.com').catch(()=>{});
Run Code Online (Sandbox Code Playgroud)


Cai*_*son 6

尽管不是万无一失,但要完成工作:

var dns = require('dns');
dns.lookupService('8.8.8.8', 53, function(err, hostname, service){
  console.log(hostname, service);
    // google-public-dns-a.google.com domain
});
Run Code Online (Sandbox Code Playgroud)

只需使用简单if(err)并充分处理响应.:)

ps.:请不要打扰告诉我8.8.8.8不是要解决的名称,它只是从谷歌查找高可用性DNS服务器.目的是检查连接性,而不是名称解析.

  • 真的没有这种"标准"方式,因为为了测试**互联网**连接,你必须在**互联网上测试一些东西**.我想你可以检查你想要的任何东西,亚马逊,isp,cdn,IDK,为了简单起见只使用谷歌,BTW使用IP使其独立于DNS. (7认同)

Jav*_*vad 6

由于我在这里关心其他解决方案中的 DNS 缓存,因此我尝试使用 http2 进行实际的连接测试。我认为这是测试互联网连接的最佳方法,因为它不会发送太多数据,也不依赖于单独的 DNS 解析,而且速度相当快。

请注意,这是在 v8.4.0 中添加的

const http2 = require('http2');

function isConnected() {
  return new Promise((resolve) => {
    const client = http2.connect('https://www.google.com');
    client.on('connect', () => {
      resolve(true);
      client.destroy();
    });
    client.on('error', () => {
      resolve(false);
      client.destroy();
    });
  });
};

isConnected().then(console.log);
Run Code Online (Sandbox Code Playgroud)

编辑:如果有人感兴趣的话,我将其制作成一个包。