5

我正在运行 node.js,如下所示:

> http = require('http')
> http.get('http://myhost.local:8080',
    function (res) { console.log("RES" + res) }
  ).on('error', function (e) { console.log("Error:", e) })

> uri = require('url').parse("http://myhost.local:8080")
{ protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'myhost.local:8080',
  port: '8080',
  hostname: 'myhost.local',
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: 'http://myhost.local:8080/' }
> http.get(uri,
    function (res) { console.log("RES" + res) }
  ).on('error', function (e) { console.log("Error:", e) })

隐式和显式解析的 URI 均引发错误,我得到以下输出:

错误:{ [错误:连接 ECONNREFUSED] 代码:'ECONNREFUSED',errno:'ECONNREFUSED',系统调用:'connect'}

主机myhost.local是 in 的别名localhost,即/etc/hosts

127.0.0.1   localhost myhost.local myhost
255.255.255.255 broadcasthost
::1             localhost myhost.local myhost
fe80::1%lo0 localhost myhost.local myhost

编辑:我几乎尝试了主机文件的所有排列,包括最明显的:

127.0.0.1   localhost 
255.255.255.255 broadcasthost
::1             localhost myhost.local myhost
fe80::1%lo0 localhost

编辑我还应该提到我现在已经在不止一台 Mac 上尝试过这个。

尽管这似乎是一个相当常见的错误,但我没有看到任何有用的解释或解决方法。以下是一些值得注意的相关事实:

  1. 运行$ wget http://myhost.local:8080按预期工作,所以它不是防火墙问题。
  2. 运行$ telnet myhost.local 8080然后手动获取 url 工作正常,所以这不是一个奇怪的 HTTP 问题。
  3. 我使用 node.js 连接到其他主机没有问题,例如http://www.google.com

我希望有用的系统信息包括:

$ node -v
v0.9.11

$ uname -a
Darwin myhost.local 12.2.1 Darwin Kernel Version 12.2.1:
Thu Oct 18 12:13:47 PDT 2012; root:xnu-2050.20.9~1/RELEASE_X86_64 x86_64

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.8.2
BuildVersion:   12C3104

$ sudo  netstat -nalt | grep LISTEN | grep 8080
tcp6       0      0  ::1.8080  *.*    LISTEN

有谁知道这里发生了什么,以及可能的修复方法是什么?

4

3 回答 3

12

我将在此处发布此内容,以防其他人遇到问题。

Bert Belder,Node.js 邮件列表:

在您的系统上,“myhost.local”解析为三个不同的地址(127.0.0.1、:::1 和 fe80::1)。Node 更喜欢 ipv4 而不是 ipv6,因此它会尝试连接到 127.0.0.1。127.0.0.1:8080 上没有任何监听,因此 connect() 系统调用失败并显示 ECONNREFUSED。Node 不会使用任何其他已解析的 IP 重试 - 它只会向您报告错误。一个简单的解决方案是将“localhost”替换为预期的目标 IP 地址“::1”。

这种行为是否正确尚有待商榷,但这就是造成这种行为的原因。

伯特

于 2013-03-06T10:33:47.933 回答
3

根据关于 nodejs/Google Groups的讨论,这源于 Node 的一个问题(尽管有一些方法可以解决它),正如@alessioalex 在他的回答中提到的那样。每个伯特贝尔德的有用评论:

应该有一个 getaddrinfo 包装器,它返回的不仅仅是第一个结果

例如,

> require('dns').lookup('myhost.local', console.log)
{ oncomplete: [Function: onanswer] }
> null '127.0.0.1' 4

getaddrinfo这是传递给 Node.js的多个结果中的第一个。似乎nodejs只使用了getaddrinfo调用的第一项。Bert 和 Ben Noordhuis 在小组讨论中一致认为,应该有一种方法可以返回不仅仅是使用getaddrinfo包装器的第一个结果。

对比 python,它返回所有结果getaddrinfo

>>> import socket
>>> socket.getaddrinfo("myhost.local", 8080)
[(30, 2, 17, '', ('::1', 8080, 0, 0)),
 (30, 1, 6, '',  ('::1', 8080, 0, 0)),
 (2, 2, 17, '',  ('127.0.0.1', 8080)),
 (2, 1, 6, '',   ('127.0.0.1', 8080)),
 (30, 2, 17, '', ('fe80::1%lo0', 8080, 0, 1)),
 (30, 1, 6, '',  ('fe80::1%lo0', 8080, 0, 1))]
于 2013-04-22T18:01:14.157 回答
0

这行得通吗?

var http = require('http');
var options = {
  host: 'myhost.local',
  port: 8080,
  path: '/'
};

http.get(options, function (res) { 
  console.log("RES" + res) 
}).on('error', function (e) { 
  console.log("Error:", e) 
});
于 2013-03-05T15:13:17.310 回答