Nodejs eaddrinuse谁知道是什么原因造成的吗?
Nodejs eaddrinuse谁知道是什么原因造成的吗?
今天child_process.fork创建一个子进程来做session服务器, 然后web服务器用socket跟session服务器交换数据, 问题是我用ab压web服务器的时候(winxp环境下apache ab -n 1000 -c 1000 http://xxx) 经常提示eaddrinuse 我很奇怪 这句话翻译不是"错误:地址使用中"么? 我只是客户端连接, 又不是监听端口 怎么会提示这个错误呢 奇怪…
2 回复
EADDRINUSE
错误表示尝试绑定到已经被占用的地址和端口。即使你只是客户端连接,但如果你在创建 Socket 时指定的地址和端口已经被其他进程或同一程序中的其他实例占用,也会遇到这个错误。
这种情况可能发生在你使用 child_process.fork
创建的子进程中,如果子进程在退出后没有正确地释放资源(如未关闭的 socket),那么在下次启动相同子进程时可能会尝试绑定到已经被占用的地址和端口。
示例代码
假设你在主进程中创建了一个子进程,并且子进程中有一个用于与 session 服务器通信的 socket:
const { fork } = require('child_process');
const net = require('net');
// 主进程
const child = fork('./sessionServer.js'); // 子进程
// 定义客户端 socket
const clientSocket = new net.Socket();
clientSocket.connect(3000, 'localhost', () => {
console.log('Connected to session server');
});
// 处理错误事件
clientSocket.on('error', (err) => {
if (err.code === 'EADDRINUSE') {
console.error('Error: Address already in use');
// 在这里可以尝试重启子进程或者等待一段时间后重试
}
});
在 sessionServer.js
中定义子进程的逻辑:
const net = require('net');
// 创建一个服务器
const server = net.createServer((socket) => {
socket.write('Welcome to the session server\n');
});
server.listen(3000, 'localhost', () => {
console.log('Session server listening on port 3000');
});
// 处理服务器关闭时的情况
process.on('SIGINT', () => {
server.close(() => {
console.log('Server closed');
process.exit(0);
});
});
解决方案
- 确保子进程正确退出:在子进程接收到
SIGINT
信号时,确保关闭所有打开的 socket。 - 增加超时处理:在客户端 socket 连接失败时,可以设置一个定时器,过一段时间后尝试重新连接。
- 检查端口是否被占用:在启动子进程之前,检查所需端口是否已经被占用。
以上是基本的排查思路和解决方案。