Nodejs随机免费tcp端口

时间:2015-01-20 16:17:21

标签: node.js tcp port

每次实例化我的类的新实例时,我的项目都需要设置一个新端口。

在Node.js中如何找到一个可在我的新套接字服务器中设置的免费TCP端口?或者检查我的指定端口是否已经使用过。

7 个答案:

答案 0 :(得分:42)

您可以通过为端口指定0来绑定到操作系统分配的随机空闲端口。这样您就不会受到竞争条件的影响(例如,在您有机会绑定它之前检查一个开放端口和一些绑定到它的进程)。

然后,您可以通过调用server.address().port来获取指定的端口。

示例:

var net = require('net');

var srv = net.createServer(function(sock) {
  sock.end('Hello world\n');
});
srv.listen(0, function() {
  console.log('Listening on port ' + srv.address().port);
});

答案 1 :(得分:3)

要查找已打开的TCP端口,您可以使用模块portastic

您可以找到这样的端口:

port = require('portastic');

options = {
    min : 8000,
    max : 8005
}

port.find(options, function(err, data){
    if(err)
        throw err;
    console.log(data);
});

答案 2 :(得分:2)

对于Express应用:

const app = require('express')();

const server = app.listen(0, () => {
  console.log('Listening on port:', server.address().port);
});

答案 3 :(得分:0)

使用portfinderget-port模块(portastic太旧了)。他们俩都做得不错。

答案 4 :(得分:0)

等待港口

对于那些尝试“同步”执行此操作的用户,下游代码取决于操作系统选择的port(例如,在创建测试服务器并将端口传递给测试时),以下食谱对我很有帮助:

export const sleepForPort = async (httpServer: Server, ms: number): Promise<number> => {
  return new Promise<number>((resolve, reject) => {
    httpServer.listen(0, async () => {
      try{
        let addr = (httpServer.address() as AddressInfo | null)
        while(! (addr && addr.port) ) {
          await sleep(ms);
          addr = httpServer.address() as AddressInfo | null
        }
        resolve(addr.port);
      }catch(e){
        reject(e);
      }
    });
  });
}

const sleep = (ms: number) => {
  return new Promise(resolve => setTimeout(resolve, ms));
}

如果在实时服务器上运行集成测试,这将使我们await端口号变为可用,并返回该端口号,以便我们的testClient可以在该端口上访问localhost

export const setupTests = async () => {
  const app = createExpressApp(...);
  const httpServer = createServer(app);
  server.installSubscriptionHandlers(httpServer); // Testing graphql subscriptions
  const port = await sleepForPort(httpServer, 100);
  return {port}
}

describe("Http server test", () => {
  let port: number;
  beforeAll(async () => {
    {port} = await setupTests()
  })
  it("Hits the right port", () => {
    const res = await fetch(`http://localhost:${port}/testing`)
    expect(res).toBeDefined()
    expect(res.status).toEqual(200);
  }
})

答案 5 :(得分:0)

在构建在本地运行的应用程序时,我在很多场合都使用了公认的答案-感谢@mscdex。但是,最近我有一个用例,如果可能的话,最好坚持使用一个给定的端口,但是如果使用该端口,则仍然要回退到另一个端口。

这样做的原因是我想使用localStorage保存应用程序首选项,该存储仅限于同一站点,并具有相同的端口以确保安全。因此,我希望在可能的情况下始终使用端口3000,但如有需要,请回退到3001或3002等,直到可用为止。如果使用的端口不是3000,那么我将退回到存储在用户硬盘上的应用程序首选项的副本。

我使用以下模式进行此操作:

ArrayDeque

const http = require('http'); const server = http.createServer(function(req,res){ ... }) const config = { port: 3000, launched: false, }; serverListen(server, config.port); function serverListen(server, port){ server.on('error', e => { console.log(`port ${config.port} is taken`) config.port +=1; server.close(); serverListen(server, config.port); }).listen(port, function() { if (config.launched){ return; } console.log('Listening on port ' + server.address().port); launchBrowser(); config.launched = true; }); } 只是一个将浏览器启动到launchBrowser()

的功能

该应用程序是一个简单的本地服务器+浏览器应用程序。浏览器是GUI,服务器则在用户的硬盘驱动器上进行文件等的修改。

答案 6 :(得分:0)

端口查找器库:

https://github.com/http-party/node-portfinder

我建议您使用 portfinder 库,它在一周内的下载量超过 1000 万次。

默认情况下,portfinder 库将从 8000 开始搜索并扫描,直到达到最大端口号 (65535)。

const portfinder = require('portfinder');

portfinder.getPort((err, port) => {
    //
    // `port` is guaranteed to be a free port
    // in this scope.
    //
});