javascript - Node.js 16 -> 17 更改了 "localhost"的分辨率?

标签 javascript node.js sockets localhost

在 node.js 16.13.1 (Windows) 下,这样的代码有效(假设服务器存在并且工作正常):

import net from 'net';

let socket = net.createConnection({
    host: 'localhost',
    port: 12345
})

更新到 node.js 17.7.2 后,上面现在抛出 ECONNREFUSED(连接被拒绝)错误。但是,它适用于“0.0.0.0”而不是“localhost”。

事实上,即使记录在案的默认“localhost”(感谢 VLAZ)在 17.7.2 上也会失败:

// connects with 16.13.1, ECONNREFUSED with 17.7.2:
net.createConnection({port:12345});

// connects with both versions:
net.createConnection({port:12345,host:'0.0.0.0'});

// connects with 16.13.1, ECONNREFUSED with 17.7.2:
net.createConnection({port:12345,host:'localhost'});

我已经确认该行为取决于 Node 的版本。我可以通过切换 Node 版本、使用任何建立网络连接的代码来可靠地避免/重现该行为。

我有相当多的主机默认为“localhost”的代码。如果不需要,我宁愿不将所有这些更新为“0.0.0.0”。更乏味的是,用户通常会提供主机地址并期望“localhost”能够工作,所以现在我每次创建一个带有用户指定主机地址的套接字时都必须添加将“localhost”转换为“0.0.0.0”的逻辑.我的意思是,我会做我必须做的事,但这种做法很糟糕。

我的问题是:16.13.1 和 17.7.2 之间发生了什么导致“localhost”不再可用?这是一个错误,还是一些有意的改变?而且,有没有办法让它再次工作,或者我现在必须到处查找并用“0.0.0.0”替换“localhost”?

我怀疑人们在互联网上询问的很多“连接被拒绝到本地主机”错误都与任何更改有关...


更新:这似乎与 17 中接口(interface)枚举方式(或类似方式)的变化有关,而不是“localhost”的具体使用。

例如,使用以下测试设置:

  • 用 Node 创建了三个 TCP 服务器:一个用于默认地址,一个明确设置了“0.0.0.0”,一个明确设置了“localhost”。
  • 三个客户端尝试连接到每个服务器,一个连接到默认主机,一个连接到“0.0.0.0”,一个连接到“localhost”。

然后是 16.13.1:

<表类="s-表"> <头> <日> 默认监听 在 0.0.0.0 上监听 在本地主机上监听 <正文> 默认连接 确定 确定 确定 连接到 0.0.0.0 确定 确定 确定 连接到本地主机 确定 确定 确定

但是对于 17.7.2:

<表类="s-表"> <头> <日> 默认监听 在 0.0.0.0 上监听 在本地主机上监听 <正文> 默认连接 确定 经济拒绝 确定 连接到 0.0.0.0 确定 确定 经济拒绝 连接到本地主机 确定 经济拒绝 确定

现在是用 Node 创建的服务器;服务器和客户端的 Node 版本也相同。在我原来的情况下,我的服务器是用 C++ 和标准 socket() 创建的API,绑定(bind)到 INADDR_ANY (0.0.0.0).

测试代码:

import net from 'net';

console.log(process.version);

const accepted = detail => socket => socket.write(detail, ()=>socket.end());

const serversReady = () => [ 
    new Promise(resolve => net.createServer(accepted('default')).listen(12345, function(){resolve(this)})),
    new Promise(resolve => net.createServer(accepted('localhost')).listen(12346, 'localhost', function(){resolve(this)})),
    new Promise(resolve => net.createServer(accepted('0.0.0.0')).listen(12347, '0.0.0.0', function(){resolve(this)}))
];

const ports = [[12345,'default'], [12346,'localhost'], [12347,'0.0.0.0']];
const hosts = [{}, {host:'localhost'}, {host:'0.0.0.0'}];

const clientsDone = () => ports.map(([port,whichserver]) => hosts.map(host => new Promise((resolve, reject) => {
    let opts = {...host, port:port};
    net.createConnection(opts)
        .on('error', e => (console.log(opts, 'to:'+whichserver, 'error', e.message), reject(e)))
        .on('data', d => console.log(opts, 'to:'+whichserver, 'read', d.toString()))
        .on('end', () => resolve());
}))).flat();

Promise.all(serversReady())
    .then(servers => Promise.allSettled(clientsDone()).then(() => servers))
    .then(servers => servers.forEach(s => s.close()));

下类后会有更多相关信息,但我想我会尽早发布这一点。也会检查 18。

最佳答案

我引用来自 @richardlau 的答案

Node.js no longer re-sorts results of IP address lookups and returns them as-is (i.e. it no longer ignores how your OS has been configured). You can change the behaviour via the verbatim option to dns.lookup() or set the --dns-result-order command line option to change the default.

您可以 ping 本地主机。如果显示:

Reply from 127.0.0.1

这意味着您的系统更喜欢 ipv4 地址来解析本地主机。如果显示:

Reply from ::1

这意味着您的系统更喜欢 ipv6 地址。

你可以 change system setting to prefer ipv4 . Node.js 将按照您的预期将 localhost 解析为 127.0.0.1。

关于javascript - Node.js 16 -> 17 更改了 "localhost"的分辨率?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72648487/

相关文章:

node.js - 工作区设置权限被拒绝

linux - 从原始套接字接收失败

javascript - 计算State数量——重构

sockets - 知道基本加密聊天的任何好例子吗? (GnuTLS?)

Linux 套接字描述符

javascript - 如何将 div 附加到变量内的另一个 div?

javascript - QUnit 没有显示我的测试

javascript - 无法使用服务器端渲染访问 DOM - react 0.14.1、react-dom 0.14.1 和 react-router 1.0.0-rc3

javascript - JS 多个长按键操作

Node .js : rendering error with vash