diff --git a/lib/detect-port.js b/lib/detect-port.js index c1cb636..70da688 100644 --- a/lib/detect-port.js +++ b/lib/detect-port.js @@ -8,26 +8,40 @@ module.exports = (port, callback) => { callback = port; port = null; } + port = parseInt(port) || 0; + let maxPort = port + 10; + if (maxPort > 65535) { + maxPort = 65535; + } + debug('detect free port between [%s, %s)', port, maxPort); if (typeof callback === 'function') { - return tryListen(port, callback); + return tryListen(port, maxPort, callback); } // promise return new Promise(resolve => { - tryListen(port, (_, realPort) => { + tryListen(port, maxPort, (_, realPort) => { resolve(realPort); }); }); }; -function tryListen(port, callback) { - port = parseInt(port) || 0; +function tryListen(port, maxPort, callback) { const server = new net.Server(); server.on('error', err => { debug('listen %s error: %s', port, err); - port = 0; + if (port === 0) { + return callback(err); + } + + port++; + if (port >= maxPort) { + debug('port: %s >= maxPort: %s, give up and use random port', port, maxPort); + port = 0; + maxPort = 0; + } server.close(); - return tryListen(port, callback); + return tryListen(port, maxPort, callback); }); server.listen({ port }, () => { diff --git a/package.json b/package.json index 5503503..dc3042e 100644 --- a/package.json +++ b/package.json @@ -20,10 +20,11 @@ }, "devDependencies": { "command-line-test": "^1.0.8", - "egg-bin": "^2.0.0", + "egg-bin": "^1.10.3", "egg-ci": "^1.1.0", "eslint": "^3.13.1", - "eslint-config-egg": "^3.1.0" + "eslint-config-egg": "^3.1.0", + "pedding": "^1.1.0" }, "scripts": { "test": "egg-bin test", diff --git a/test/detect-port.test.js b/test/detect-port.test.js index fada974..b1f7c68 100644 --- a/test/detect-port.test.js +++ b/test/detect-port.test.js @@ -2,16 +2,24 @@ const assert = require('assert'); const net = require('net'); +const pedding = require('pedding'); const detectPort = require('..'); describe('detect port test', () => { - let server; + const servers = []; before(done => { - server = new net.Server(); - server.listen(7001, done); + done = pedding(11, done); + const server = new net.Server(); + server.listen(3000, done); + servers.push(server); + for (let port = 7000; port < 7010; port++) { + const server = new net.Server(); + server.listen(port, done); + servers.push(server); + } }); after(() => { - server.close(); + servers.forEach(server => server.close()); }); it('get random port', done => { @@ -29,11 +37,18 @@ describe('detect port test', () => { }); }); - it('work with listening port', done => { - const port = 7001; + it('work with listening next port 3001', done => { + const port = 3000; detectPort(port, (_, realPort) => { - assert(realPort !== 7001); - assert(realPort > 0); + assert(realPort === 3001); + done(); + }); + }); + + it('work with listening random port when try port hit maxPort', done => { + const port = 7000; + detectPort(port, (_, realPort) => { + assert(realPort < 7000 || realPort > 7009); done(); }); });