Node.js指定hostname时出现EADDRINUSE错误的排查求助
分析你的EADDRINUSE错误原因
首先看你的代码和报错信息,这里有几个关键问题需要拆解:
1. 代码里的两个致命问题
先看你贴的代码片段:
const express = require('express') const http = require('http') const hostname = 'localhost' const port = 3000 const app = express() app.use((req, res, next) => { console.log(req.headers) res.statusCode = 200 res.setHeader('Content-Type', 'text/html') res.end('<html><body><h1>This is response</h1></body></html>') }) // 这里的`server`还没定义,执行到这行先触发ReferenceError server.listen(hostname,port, () => { console.log(`Server running at http:${hostname}//:${port}`) }) const server = http.createServer(app) // 即使上面的错误被忽略,这里又重复调用listen同一个端口+主机 server.listen(hostname,port, () => { console.log(`Server running at http:{}//:${port}`) })
- 变量顺序错误:你在定义
server变量之前就调用了server.listen(),这会先抛出ReferenceError; - 重复监听:假设你实际代码顺序是先创建
server再调用两次listen(),或者同时用app.listen()(Express内部会自动创建新的Server实例)和server.listen(),那么同一个hostname:port组合会被两个套接字/进程尝试监听,直接触发EADDRINUSE——因为系统不允许同一个IP端口被多个监听者占用。
2. 为什么去掉hostname就能正常运行?
当你不指定hostname时,Node.js默认会监听0.0.0.0(即所有可用的网络接口),而指定localhost时,会精准监听127.0.0.1(仅本地回环接口)。
你说去掉hostname就正常,大概率是因为:
- 原代码里的
ReferenceError导致第一次server.listen()根本没执行,而当你去掉hostname后,第二次server.listen(port)能正常启动; - 或者你误打误撞在去掉hostname时,注释/删除了其中一次重复的监听调用,避免了端口冲突。
修复方案
- 修正变量顺序:确保调用
server.listen()前,先定义server变量; - 移除重复监听:只保留一次监听逻辑——要么用Express封装的
app.listen(),要么手动创建Server实例后调用server.listen(),不要同时使用; - 正确的示例代码:
const express = require('express') const http = require('http') const hostname = 'localhost' const port = 3000 const app = express() app.use((req, res, next) => { console.log(req.headers) res.statusCode = 200 res.setHeader('Content-Type', 'text/html') res.end('<html><body><h1>This is response</h1></body></html>') }) // 方案1:用Express的app.listen(推荐,更简洁) app.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}`) }) // 或者方案2:手动创建Server实例 // const server = http.createServer(app) // server.listen(port, hostname, () => { // console.log(`Server running at http://${hostname}:${port}`) // })
另外,建议你检查控制台是否有ReferenceError的报错,这个错误可能被后面的EADDRINUSE掩盖,导致你误以为是端口占用的单一问题。
内容的提问来源于stack exchange,提问作者Shikhar Tandon
相关产品推荐
相关产品推荐

