Ionică Bizău
Ionică Bizău

Reputation: 113365

How can I check if port is busy in NodeJS?

How can I check if port is busy for localhost?

Is there any standard algorithm? I am thinking at making a http request to that url and check if response status code is not 404.

Upvotes: 31

Views: 59523

Answers (6)

snnsnn
snnsnn

Reputation: 13620

I needed a simple solution to find an available port for a local server, which I keep it here for future reference:

import { createServer } from 'node:net';

async function findPort(port: number) {
  const server = createServer();
  return new Promise(resolve => {
    server.once('listening', () => {
      server.close();
      resolve(port);
    }).on('error', () => {
      port += 1;
      server.listen(port);
    }).listen(port);
  });
}

// Use it in an async function
const port = await findPort(3000);

If you need a test case to block multiple servers:

// run-servers.js
const { createServer } = require("net");

for (let index = 3000; index <= 6000; index++) {
  const server = createServer();
  server.listen(index);
}

Run it:

node run-server.js

Upvotes: 1

Tyson
Tyson

Reputation: 39

check without producing an error on mac and most unix/linux

const { spawnSync } = require('child_process')

function checkPort(port) {
  const output = spawnSync(
    `lsof -i tcp:${port} | awk '{print $2}' |grep --invert PID`,
    { shell: true }
  )
  if (output.error) {
    console.error(output.error)
    return
  }
  const pid = Buffer.from(output.stdout.buffer).toString().split('\n')[0]
  console.log({ pid })
  return pid
}

const pid = checkPort(443)
if (pid) {
  console.log(`the server is running, process id: ${pid}`)
}

Upvotes: 1

ben
ben

Reputation: 818

this is what im doing, i hope it help someone


const isPortOpen = async (port: number): Promise<boolean> => {
    return new Promise((resolve, reject) => {
        let s = net.createServer();
        s.once('error', (err) => {
            s.close();
            if (err["code"] == "EADDRINUSE") {
                resolve(false);
            } else {
                resolve(false); // or throw error!!
                // reject(err); 
            }
        });
        s.once('listening', () => {
            resolve(true);
            s.close();
        });
        s.listen(port);
    });
}

const getNextOpenPort = async(startFrom: number = 2222) => {
    let openPort: number = null;
    while (startFrom < 65535 || !!openPort) {
        if (await isPortOpen(startFrom)) {
            openPort = startFrom;
            break;
        }
        startFrom++;
    }
    return openPort;
};


you can use isPortOpen if you just need to check if a port is busy or not. and the getNextOpenPort finds next open port after startFrom. for example :

let startSearchingFrom = 1024;
let port = await getNextOpenPort(startSearchingFrom);
console.log(port);

Upvotes: 2

Ido
Ido

Reputation: 2054

Thank to Steven Vachon link, I made a simple example:

const net = require("net");
const Socket = net.Socket;

const getNextPort = async (port) =>
{
    return new Promise((resolve, reject) =>
    {
        const socket = new Socket();

        const timeout = () =>
        {
            resolve(port);
            socket.destroy();
        };

        const next = () =>
        {
            socket.destroy();
            resolve(getNextPort(++port));
        };

        setTimeout(timeout, 10);
        socket.on("timeout", timeout);

        socket.on("connect", () => next());

        socket.on("error", error =>
        {
            if (error.code !== "ECONNREFUSED")
                reject(error);
            else
                resolve(port);
        });

        socket.connect(port, "0.0.0.0");
    });
};

getNextPort(8080).then(port => {
    console.log("port", port);
});

Upvotes: 7

Codebling
Codebling

Reputation: 11382

Check out the amazing tcp-port-used node module!

//Check if a port is open
tcpPortUsed.check(port [, host]) 

 //Wait until a port is no longer being used
tcpPortUsed.waitUntilFree(port [, retryTimeMs] [, timeOutMs])

//Wait until a port is accepting connections
tcpPortUsed.waitUntilUsed(port [, retryTimeMs] [, timeOutMs])

//and a few others!

I've used these to great effect with my gulp watch tasks for detecting when my Express server has been safely terminated and when it has spun up again.

This will accurately report whether a port is bound or not (regardless of SO_REUSEADDR and SO_REUSEPORT, as mentioned by @StevenVachon).

The portscanner NPM module will find free and used ports for you within ranges and is more useful if you're trying to find an open port to bind.

Upvotes: 17

hexacyanide
hexacyanide

Reputation: 91649

You could attempt to start a server, either TCP or HTTP, it doesn't matter. Then you could try to start listening on a port, and if it fails, check if the error code is EADDRINUSE.

var net = require('net');
var server = net.createServer();

server.once('error', function(err) {
  if (err.code === 'EADDRINUSE') {
    // port is currently in use
  }
});

server.once('listening', function() {
  // close the server if listening doesn't fail
  server.close();
});

server.listen(/* put the port to check here */);

With the single-use event handlers, you could wrap this into an asynchronous check function.

Upvotes: 40

Related Questions