Nodejs random free tcp ports

node.jsTcpPort

node.js Problem Overview


My project need to setup a new port every time a new instance of my class is instantiated.

In Node.js how I can find a free TCP port to set in my new socket server? Or check if my specified port is already used or not.

node.js Solutions


Solution 1 - node.js

You can bind to a random, free port assigned by the OS by specifying 0 for the port. This way you are not subject to race conditions (e.g. checking for an open port and some process binding to it before you get a chance to bind to it).

Then you can get the assigned port by calling server.address().port.

Example:

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

Solution 2 - node.js

For Express app:

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

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

Solution 3 - node.js

To find an opened TCP's port you can use the module portastic

You can find a port like this:

port = require('portastic');

options = {
    min : 8000,
    max : 8005
}

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

Solution 4 - node.js

Port Finder Library:

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

I suggest you use portfinder library, it has over 10 million downloads in a week.

By default portfinder library will start searching from 8000 and scan until the maximum port number (65535) is reached.

const portfinder = require('portfinder');

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

Solution 5 - node.js

I use this compact form:

import net from "net"

async function getPortFree() {
	return new Promise( res => {
		const srv = net.createServer();
		srv.listen(0, () => {
			const port = srv.address().port
			srv.close((err) => res(port))
		});
	})
}

use:

const PORT = await getPortFree()

Solution 6 - node.js

Await'ing the port

For those of you trying to do this "synchronously", with downstream code dependent on the port that is chosen by the OS (e.g. while creating a test server and passing the port to tests), the following recipe has served me well:

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

If running integration tests against a live server, this allows us to await the port number becoming available, and return this so our testClient can hit localhost on this port!

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

Solution 7 - node.js

I've used the accepted answer on numerous occasions when building apps that run locally - thanks @mscdex. However, I had a use case recently when it would be preferable to stick to a given port if possible, but still to fallback to another port if that one is taken.

The reason for this is I wanted to save app preferences using localStorage, which is restricted to the same site, with the same port for security. Therefore, I wanted to always use port 3000 when possible, but if needed fallback to 3001, or 3002, etc. until one is available. If the port being used is not 3000, then I fallback to a copy of the app preferences stored on the user's hard disk.

I do this with this pattern:

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() is just a function that launches the browser to 'http://127.0.0.1:' + server.address().port

The app is a simple local server + browser app. With the browser being the GUI and the server doing the modification of files etc. on the user's harddrive.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMarcos BergamoView Question on Stackoverflow
Solution 1 - node.jsmscdexView Answer on Stackoverflow
Solution 2 - node.jsNinh PhamView Answer on Stackoverflow
Solution 3 - node.jsMarcos BergamoView Answer on Stackoverflow
Solution 4 - node.jsLong NguyenView Answer on Stackoverflow
Solution 5 - node.jspriolo priolusView Answer on Stackoverflow
Solution 6 - node.jsThe AelfinnView Answer on Stackoverflow
Solution 7 - node.jsAlex LView Answer on Stackoverflow