Node.js 检测端口是否被占用:原生无依赖方案(附批量检测)
用 Node.js 实现检测指定端口是否被占用的方案,以下提供两种实用写法(原生 net 模块,无第三方依赖),包括「单个端口检测」和「批量端口检测」,代码可直接运行,适配日常开发/运维场景。
一、核心原理
Node.js 内置的 net 模块可创建 TCP 服务器,核心逻辑:
- 尝试让服务器监听指定端口;
- 若监听失败且错误码为
EADDRINUSE → 端口被占用;
- 若监听成功 → 端口未被占用(需立即关闭服务器,避免占用端口)。
这种方式是最可靠的原生方案,无需安装任何依赖,适配所有 Node.js 版本。
二、完整实现代码
1. 基础版:检测单个端口是否被占用
封装为 Promise 函数,支持异步调用(推荐,适配 async/await):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| const net = require('net');
function checkPortIsUsed(port, host = '127.0.0.1') { return new Promise((resolve) => { const server = net.createServer(); server.unref();
server.on('error', (err) => { if (err.code === 'EADDRINUSE') { resolve(true); } else { resolve(true); } });
server.listen(port, host, () => { server.close(); resolve(false); }); }); }
async function testSinglePort() { const port = 3000; const isUsed = await checkPortIsUsed(port); console.log(`端口 ${port} ${isUsed ? '已被占用' : '未被占用'}`); }
testSinglePort();
|
2. 进阶版:批量检测多个端口
适合一次性检测多个常用端口(如 3000、8080、9000):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| const net = require('net');
function checkPortIsUsed(port, host = '127.0.0.1') { return new Promise((resolve) => { const server = net.createServer().unref(); server.on('error', (err) => resolve(err.code === 'EADDRINUSE')); server.listen(port, host, () => { server.close(); resolve(false); }); }); }
async function checkMultiPorts(ports) { const result = {}; const promises = ports.map(async (port) => { result[port] = await checkPortIsUsed(port); }); await Promise.all(promises); return result; }
async function testMultiPorts() { const ports = [3000, 8080, 9000, 80, 443]; const portStatus = await checkMultiPorts(ports); console.log('批量端口检测结果:'); Object.entries(portStatus).forEach(([port, isUsed]) => { console.log(`端口 ${port}:${isUsed ? '✅ 已占用' : '❌ 未占用'}`); }); }
testMultiPorts();
|
三、关键细节说明
- **
server.unref()**:禁用服务器的“引用计数”,避免检测脚本因服务器未关闭而一直运行;
- **错误码
EADDRINUSE**:Node.js 中表示“地址已被占用”的标准错误码,是判断端口占用的核心依据;
- 异步封装:用 Promise 封装,适配
async/await,避免回调地狱,符合现代 Node.js 开发习惯;
- **主机参数
host**:默认检测本地(127.0.0.1),若需检测外网端口,可传入公网 IP/域名(如 0.0.0.0)。
四、扩展场景:检测端口占用后自动选可用端口
开发中常用的“端口被占用则自动换端口”功能,基于上述函数实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
|
async function findAvailablePort(startPort) { let currentPort = startPort; while (currentPort < 65535) { const isUsed = await checkPortIsUsed(currentPort); if (!isUsed) { return currentPort; } currentPort++; } throw new Error('未找到可用端口(1-65535)'); }
findAvailablePort(3000).then((port) => { console.log(`找到可用端口:${port}`); });
|
总结
关键点回顾
- 核心原理:通过
net.createServer() 尝试监听端口,捕获 EADDRINUSE 错误判断占用;
- 基础用法:单个端口检测封装为 Promise 函数,异步调用更友好;
- 进阶用法:批量检测/自动找可用端口,适配开发场景;
- 优势:原生无依赖、跨平台(Windows/Linux/macOS 通用)、结果可靠。