【问题标题】:How does Node.js choose random ports?Node.js 如何选择随机端口?
【发布时间】:2012-04-11 15:55:27
【问题描述】:

使用 Node.js,我们可以创建一个服务器并监听一个随机端口:

var server = net.createServer();
server.listen(0, '127.0.0.1');

第一个参数port0表示选择随机端口,127.0.0.1表示只监听localhost,as documented

Node.js 是否选择了未使用的端口?如果 Node.js 碰巧选择了一个已经打开并绑定到另一个应用程序的端口,我是否必须自己检查并重试?它会选择任何旧端口,还是只选择用户端端口 (>1024)?

【问题讨论】:

  • 我认为它只是分配了一个随机端口,但我不是 100%。我认为您需要执行错误和增量等...就像在链接中一样(尽管他们使用相同的端口重试)
  • 但是你不得不想知道在某个随机可用端口上启动意味着什么 - 除非你有某种服务发现,否则其他人和客户很难发现你随机发现的东西 :)
  • 这通常不是问题,因为您会同意端口或使用知名端口。如果您没有绑定该端口的权限,那么您还有其他问题需要解决。
  • @bryanmac,我有特定的理由绑定到随机端口。请参阅stackoverflow.com/questions/9881305/… 绑定后,我可以轻松调用server.address() 以获取我所在的端口。

标签: node.js port


【解决方案1】:

操作系统分配端口号。见https://github.com/joyent/node/blob/v0.6.11/lib/net.js#L780-783

在 OS X 上,分配是顺序的、用户态的,并且不检查端口以确认它没有被使用。

在 Ubuntu 11.04 上,分配是随机的、用户态的,也不会检查端口是否正在使用中。

以下脚本可用于在其他平台上进行测试。为了验证端口是用户空间,我通过 bash 将脚本运行了 10,000 次,通过管道连接到 grep -c "p​​ort: [0-9]{1,3}" ,匹配为零。

var net = require('net'),
    firstPort;

(function createServer(port) {
  var server = net.createServer();
  server.listen(port, function() {
    address = server.address();
    if (port === 0) { 
      if (firstPort === undefined) {
        firstPort = address.port;
        // cause a EADDRINUSE in 10 more sockets for sequential platforms
        // without this, will run out of fd's before hitting EADDRINUSE
        createServer(firstPort + 10); 
        console.log('addr in use port trap: ', firstPort + 10);
      } else {
        // on OS X (sequential) this will increment the OS's sequential counter
        // and not cause EADDRINUSE
        createServer(address.port + 1);
      }
      createServer(0);
    }
    console.log("requested port:", port, " binded port:",address.port);
  });  
})(0);

【讨论】:

  • 操作系统确实会跳过正在使用的端口。您的代码中有一个错误。碰撞发生在createServer(address.port + 1) 而不是createServer(0)
  • 这里的代码展示了它在 macOS 上跳过了一个被占用的端口:gist.github.com/Trott/4caed3e2ce93a92318ec1d54aedbbc80
【解决方案2】:

Node.js 是否选择了未使用的端口?

是的,该端口将是一个可用端口。 操作系统选择一个未使用的端口而不是 Node.js,但从最终用户的角度来看,这或多或少是一回事。

在 2012 年最初发布此问题时,文档无疑有不同的措辞,但截至目前(2019 年 1 月),it is explicit about this:“如果端口被省略或为 0,操作系统将分配任意未使用的端口...”。

如果 Node.js 碰巧选择了一个已经打开并绑定到另一个应用程序的端口,我是否必须检查自己并重试?

不,你没有。无论如何,您都应该处理错误,因为任何数量的事情都可能出错。但是您不需要编写额外的代码来测试端口可用性。

它会选择任何旧端口,还是只选择用户端端口 (>1024)?

据我所知,它永远是一个非特权端口。


对于像 macOS 这样按顺序分配可用端口的操作系统,这里的代码显示操作系统将在端口不可用时跳过它。

// Testing for macOS, which supplies available ports sequentially.

var net = require('net');

createServer(0, function () {
  var port = this.address().port;
  console.log('server was assigned port ' + port);
  createServer(port+1, function () {
    var port = this.address().port;
    console.log('server was assigned port ' + port);
    createServer(0, function () {
      var port = this.address().port;
      // This line will show that the OS skipped the occupied port and assigned the next available port.
      console.log('server was assigned port ' + port);
    });
  });
});

function createServer(port, callback) {
  console.log('create server with port ' + port);
  var server = net.createServer();
  server.listen(port, callback).unref();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-07
    • 1970-01-01
    • 1970-01-01
    • 2011-08-18
    相关资源
    最近更新 更多