2013-03-05 36 views
4

我正在運行的node.js如下:莫名node.js的HTTP連接拋ECONNREFUSED(IPv6的?)

> 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和我碰到下面的輸出兩個:

Error: { [Error: connect ECONNREFUSED] code: 'ECONNREFUSED', errno: 'ECONNREFUSED', syscall: 'connect' }

主機myhost.local是用於/etc/hostslocalhost的別名,是:

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 

編輯:我試過幾乎所有排列的hosts文件,其中最明顯的:

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然後手動GET'ing網址工作正常,所以它不是一個奇怪的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 

有沒有人有一個修復可能是任何想法是怎麼回事,什麼?

+0

你,如果你使用'localhost',而不是'myhost.local'得到同樣的錯誤? – JohnnyHK 2013-03-05 15:13:02

+0

東西在本地主機上運行:80? – Floby 2013-03-05 15:13:27

+0

@JohnnyHK,@Floby:連接到的應用程序是Google App Engine,它綁定到'myhost'。讓我發佈我的'netstat'輸出雖然 - 它可能是照亮 – 2013-03-05 15:15:10

回答

7

我打算在這裏發帖以防萬一別人有問題。

伯特Belder,Node.js的郵件列表:

On your system "myhost.local" resolves to three different addresses (127.0.0.1, ::1, and fe80::1). Node prefers ipv4 over ipv6 so it'll try to connect to 127.0.0.1. Nothing is listening on 127.0.0.1:8080 so the connect() syscall fails with ECONNREFUSED. Node doesn't retry with any of the other resolved IPs - it just reports the error to you. A simple solution would be to replace 'localhost' by the intended destination ip address, '::1'.

Whether this behavior is right is somewhat open for debate, but this is what causes it.

Bert

+0

謝謝alessioalex。我很抱歉,但是我提到我嘗試了'/ etc/hosts'文件的每個變化,包括只有':: 1 localhost myhost.local'。無濟於事。 – 2013-03-06 12:06:55

+0

我應該注意到解決方案是將服務器綁定到IPv4,但這當然是錯誤的解決方案。 :) – 2013-03-06 12:15:46

+0

「節點偏好ipv4 over ipv6」絕對是錯誤的行爲。參見[RFC 6724](https://tools.ietf.org/html/rfc6724)。 – 2013-03-09 04:10:06

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) 
}); 
+0

謝謝曼紐爾。這與'require('url')。parse(「http://myhost.local:8080 /」)'是一樣的,這是http.get在傳遞字符串時調用的。爲了清楚起見,我已更新了我的問題以反映此問題 – 2013-03-05 15:22:55

3

這從節點的問題朵朵(儘管有辦法解決它),按照該discussion on nodejs/Google Groups,如@alessioalex在他的回答暗示。每伯特Belder甲有用的註釋:

there should be a getaddrinfo wrapper that returns more that just the first result

例如,

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

這是第一個多getaddrinfo結果傳遞給節點。看來nodejs只使用getaddrinfo調用的第一項。 Bert和Ben Noordhuis在小組討論中同意,應該有一種方法可以返回比getaddrinfo包裝更多的第一個結果。

對比度蟒蛇,它返回從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))] 
相關問題