我的项目需要在每次实例化我的类时设置一个新的端口。
在Node.js中,我如何找到一个空闲的TCP端口以设置我的新套接字服务器?或者检查我指定的端口是否已经被使用了。
在Node.js中,我如何找到一个空闲的TCP端口以设置我的新套接字服务器?或者检查我指定的端口是否已经被使用了。
0
来绑定一个随机的、自由分配的端口。这样,您就不会受到竞态条件(例如,在您有机会绑定到端口之前,检测到一个开放的端口和一些进程绑定到该端口)的影响。server.address().port
来获取分配的端口。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);
});
对于 Express 应用程序:
const app = require('express')();
const server = app.listen(0, () => {
console.log('Listening on port:', server.address().port);
});
我使用这种简洁的形式:
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))
});
})
}
用途:
const PORT = await getPortFree()
端口查找库:
https://github.com/http-party/node-portfinder
我建议你使用portfinder
库,它在一周内已经下载了超过1000万次。
默认情况下,portfinder
库会从8000开始搜索,并扫描到达最大端口号(65535)。
const portfinder = require('portfinder');
portfinder.getPort((err, port) => {
//
// `port` is guaranteed to be a free port
// in this scope.
//
});
要找到已打开的TCP端口,您可以使用模块portastic
您可以像这样查找端口:
port = require('portastic');
options = {
min : 8000,
max : 8005
}
port.find(options, function(err, data){
if(err)
throw err;
console.log(data);
});
portfinder
(https://www.npmjs.com/package/portfinder) 是更好的模块来处理这种情况。它甚至已经包含了 TypeScript 类型! - derpedy-dooconst 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()
是一个启动浏览器的函数,用于打开链接 'http://127.0.0.1:' + server.address().port
这个应用是一个简单的本地服务器加浏览器应用。浏览器界面为 GUI,服务器则在用户硬盘上进行文件修改等操作。
对于那些试图以“同步”的方式进行操作,且下游代码依赖于由操作系统选择的端口
(例如,在创建测试服务器并将端口传递给测试时),以下方法一直对我很有用:
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));
}
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);
}
})
error.code === 'EADDRINUSE'
,则说明该端口已被占用。 - mscdexhttp.createServer(...).listen()
! - junvarsrv.listen(process.env.PORT || 0);
。 - Besworks