nodejs中如何解除已绑定的端口
我有nodejs进程A和nodejs进程B。进程A在9000端口开了一个http server。进程B不断尝试绑定9000端口,并且由于端口已被占用而失败。这很正常。
现在进程A想要释放绑定的9000端口以使得进程B可以绑定。可是进程A不能退出。该如何做到呢?
补充
@Larvata 感谢你,你的代码是能够释放原端口的。我发现是我错误的描述了我的问题,补充如下:
我在windows上使用nodeJS启动一个http服务A。为了防止它挂掉,我启动了一个后备的http服务B,服务B会不断的尝试绑定同一个端口。如果http服务A因为某种原因退出了进程,那么服务B就会拿到那个端口的控制权,以替代http服务A。这个过程我可以通过代码完成。
然后我尝试将这个手动过程写入代码。代码会不断尝试绑定9000端口,绑定成功则提供http服务,并且开一新的进程,启动同一套代码:不断尝试绑定9000端口,绑定成功则代替前一个服务,并且开一个新的进程……
也就是进程A会开启进程B作为备胎,当进程A挂掉以后进程B会转正,并且开启进程C作为备胎……
由于开启的备胎显然不能随主进程挂掉而一起挂掉,所以有两种开启方法:
1. 通过windows的"start node xxx.js"命令启动
2. 通过cp.spawn的detached模式启动
备胎启动很顺利,但是遇到的问题是,进程A挂掉的时候,并没有将9000端口给释放,所以进程B一直无法绑定9000端口。端口只有当进程B也挂掉的时候才会被释放。但是我觉得这是说不通的,端口9000应该跟进程A一起释放才对,这种情况更像是一种port leak。
因为实际中无法决定进程A是怎么挂掉的,所以进程A不能主动关闭端口,所以我之前的问题归纳出现了问题。。。
附可执行代码(windows only)
var express = require('express');
var http = require('http');
var app = express();
var cp = require('child_process');
var server = http.createServer(app);
server.setTimeout(1000);
server.on('error', function(){
console.log("Error:", arguments);
setTimeout(tryToConnect, 3000);
});
server.on('listening', function()
{
console.log("Listening");
// var child = cp.spawn('node', ['donoting.js'], {
// detached: true,
// stdio: ['ignore', 'ignore', 'ignore']
// });
// child.unref();
cp.exec('start node listen.js');
});
var tryToConnect = function()
{
var port = 9000;
console.log("Trying to connect to port", 9000);
server.listen(9000);
};
tryToConnect();
代码应该达到的效果,应该是启动另一个窗口,然后当你把第一个关掉以后,新窗口中启动的程序取代关掉的程序。
Answers
大致写了个demo
访问
http://127.0.0.1:8001/change
之后 会释放8001 并且重新绑定8002端口
这个需要用chrome测试 ie有10-20秒的延迟 不清楚具体原因 可能与keepalive有关
http = require 'http'
openedSockets=[]
isClosing=false
onServerClose=()->
console.log 'Server port released'
isClosing=false
server.listen 8002, '127.0.0.1'
console.log 'Server running at http://127.0.0.1:8002/'
connListener=(req, res)->
res.writeHead 200, {'Content-Type': 'text/plain'}
res.end 'Hello World\n'
if req.url is '/change'
console.log "try closing"
isClosing=true
server.close onServerClose
for socket in openedSockets
socket.end ()->
socket.destroy
server = http.createServer connListener
server.on 'connection',(socket)->
openedSockets.push socket
server.listen 8001, '127.0.0.1'
console.log 'Server running at http://127.0.0.1:8001/'