我使用:
创建了一个http服务器 var server = http.createServer()
我想关闭服务器。据推测,我打电话来这样做:
server.close()
但是,这只会阻止服务器接收任何新的http连接。它不会关闭任何仍然打开的。 http.close()
接受回调,并且在所有打开的连接实际断开之前,该回调不会执行。有没有办法强制关闭一切?
问题的根源在于我有Mocha测试,在他们的设置(beforeEach()
)中启动一个http服务器,然后在他们的拆卸(afterEach()
)中关闭它。但由于仅调用server.close()
不会完全关闭,因此后续http.createServer()
通常会导致EADDRINUSE
错误。等待close()
完成也不是一种选择,因为打开连接可能需要很长时间才能完成。
我需要一些强制关闭连接的方法。我能够做这个客户端,但强制关闭我的所有测试连接,但我宁愿做服务器端,即只是告诉http服务器硬关闭所有套接字。
答案 0 :(得分:39)
你需要
connection
事件并将打开的套接字添加到数组close
事件并从阵列中删除已关闭的套件来跟踪打开的套接字destroy
您还有机会在子进程中运行服务器,并在需要时退出该进程。
答案 1 :(得分:9)
对于偶然发现此问题的其他人的参考,https://github.com/isaacs/server-destroy库为destroy()
服务器提供了一种简便的方法(使用Ege描述的方法)。
答案 2 :(得分:5)
我通常使用类似的东西:
var express = require('express');
var server = express();
/* a dummy route */
server.get('/', function (req, res) {
res.send('Hello World!');
});
/* handle SIGTERM and SIGINT (ctrl-c) nicely */
process.once('SIGTERM', end);
process.once('SIGINT', end);
var listener = server.listen(8000, function(err) {
if (err) throw err;
var host = listener.address().address;
var port = listener.address().port;
console.log('Server listening at http://%s:%s', host, port);
});
var lastSocketKey = 0;
var socketMap = {};
listener.on('connection', function(socket) {
/* generate a new, unique socket-key */
var socketKey = ++lastSocketKey;
/* add socket when it is connected */
socketMap[socketKey] = socket;
socket.on('close', function() {
/* remove socket when it is closed */
delete socketMap[socketKey];
});
});
function end() {
/* loop through all sockets and destroy them */
Object.keys(socketMap).forEach(function(socketKey){
socketMap[socketKey].destroy();
});
/* after all the sockets are destroyed, we may close the server! */
listener.close(function(err){
if(err) throw err();
console.log('Server stopped');
/* exit gracefully */
process.exit(0);
});
}
就像EgeÖzcan所说的那样,只需在连接事件中收集套接字,并在关闭服务器时将其销毁。
答案 3 :(得分:1)
我的方法来自this one,它基本上是@EgeÖzcan所说的。
唯一的补充是我设置了关闭服务器的路由,因为节点没有从我的终端('SIGTERM'
和'SIGINT'
)获取信号。
嗯,节点在执行node whatever.js
时从我的终端获取信号,但在将该任务委托给脚本时(如package.json中的'start'
脚本 - > npm start
它无法被Ctrl+C
关闭,所以这种方法对我有用。
请注意我在 Cygwin 之下,并且在此之前杀死服务器意味着关闭终端并重新打开它。
另请注意,我使用快递作为路由内容。
var http=require('http');
var express= require('express');
var app= express();
app.get('/', function (req, res) {
res.send('I am alive but if you want to kill me just go to <a href="/exit">/exit</a>');
});
app.get('/exit', killserver);
var server =http.createServer(app).listen(3000, function(){
console.log('Express server listening on port 3000');
/*console.log(process);*/
});
// Maintain a hash of all connected sockets
var sockets = {}, nextSocketId = 0;
server.on('connection', function (socket) {
// Add a newly connected socket
var socketId = nextSocketId++;
sockets[socketId] = socket;
console.log('socket', socketId, 'opened');
// Remove the socket when it closes
socket.on('close', function () {
console.log('socket', socketId, 'closed');
delete sockets[socketId];
});
// Extend socket lifetime for demo purposes
socket.setTimeout(4000);
});
// close the server and destroy all the open sockets
function killserver() {
console.log("U killed me but I'll take my revenge soon!!");
// Close the server
server.close(function () { console.log('Server closed!'); });
// Destroy all open sockets
for (var socketId in sockets) {
console.log('socket', socketId, 'destroyed');
sockets[socketId].destroy();
}
};
答案 4 :(得分:1)
我使用现代JS重写原始答案:
const server1 = http.createServer(/*....*/);
const server1Sockets = new Set();
server1.on("connection", socket => {
server1Sockets.add(socket);
socket.on("close", () => {
server1Sockets.delete(socket);
});
});
function destroySockets(sockets) {
for (const socket of sockets.values()) {
socket.destroy();
}
}
destroySockets(server1Sockets);