问题
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.
回答1:
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);
}
});
回答2:
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)
})
回答3:
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);
}
});
来源:https://stackoverflow.com/questions/22262128/node-httpserver-eaddrinuse-and-next-port