Вопрос

I try to increment a port number based on 8000 if the port is busy with EADDRINUSE, and I thought it's as easy as the below:

            var tryToOpenServer = function(port)
            {
              console.log('trying to Open: ' + port);

              HTTPserver
                .listen(port, function()
                {
                  console.log('HTTP listening:' + port);
                })
                .on('error', function(err)
                {
                  if (err.code === 'EADDRINUSE')
                  {
                    // port is currently in use
                    console.log('server Open error:' + port);

                    tryToOpenServer(port + 1);
                  }
                });

            };

            tryToOpenServer(8000);

If the port:8000 is busy and got err.code === 'EADDRINUSE', the port is incremented and the code tries the port. The problem is that

                .listen(port, function()
                {
                  console.log('HTTP listening:' + port);
                })

The above code somehow successfully runs on port:8000 even it throws an 'EADDRINUSE', so I've got 2 notifications: HTTP 8000 and 8001.

What do I miss? Please let me know thanks.

Это было полезно?

Решение

This is a Bad Idea.

Your recursion creates listeners exponentially.

If we modify your code at this Gist to track each listener that is created, we can see what happens. When I run the code and port 8000 is available, things are fine..

When 8000 is busy 8001 is available, I start to see multiple listeners..:

trying to Open: 8000
server Open error:8000
we have created 1 error event handler from 0
trying to Open: 8001
we have created 1 http server from caller 0
HTTP listening:8000
we have created 2 http server from caller 1
HTTP listening:8001

The first listener from trying port 8000 doesn't disappear.

Worse, the error listener doesn't disappear either. As more error listeners are created, every one fires on each error.

When I run your original code and both 8000 and 8001 are busy, I get these results with seven error event listeners and eight http listener functions created.

The fourth time, counts were in the 32k range and node was throwing warnings about leaks.

A better way, based on the code from Node's net documentation, might look like this. The single error handler can deal with the EADDRINUSE error each time it arises:

var http = require('http');
var port = 8000;
var HTTPserver = http.createServer(function (request, response) {
    response.writeHead(200);
    response.end("hello from server on port: " + port);
});
console.log('trying to Open: ' + port);
HTTPserver
  .listen(port, function () {
    console.log('we have created ' + listenerCounter + ' http server listeners');
    listenerCounter++;
    console.log('HTTP listening:' + port);
  })
  .on('error', function (err) {
    if (err.code === 'EADDRINUSE') {
      port++;
      console.log('Address in use, retrying on port ' + port);
      setTimeout(function () {
        HTTPserver.listen(port);
      }, 250);
    }
  });

Другие советы

Make it easy and use portscanner

https://github.com/baalexander/node-portscanner

portscanner.findAPortNotInUse(8000, 9000, '127.0.0.1', function(error, port) {
     console.log('AVAILABLE PORT AT: ' + port)
})

This works and is simple:

    var port = 8000;
    HTTPserver
      .listen(port, function()
      {
        console.log('HTTP listening:' + port);
      })
      .on('error', function(err)
      {
        if (err.code === 'EADDRINUSE')
        {
          // port is currently in use
          console.log('server Open error:' + port);

          port++;
          HTTPserver
            .listen(port);
        }
      });
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top