36

以下を使用して作成されたhttpサーバーがあります。

var server = http.createServer()

サーバーをシャットダウンしたい。おそらく、次のように呼び出してこれを行います。

server.close()

ただし、これはサーバーが新しい http 接続を受信できないようにするだけです。まだ開いているものは閉じません。http.close()はコールバックを受け取り、開いているすべての接続が実際に切断されるまで、そのコールバックは実行されません。すべてを強制的に閉じる方法はありますか?

私にとっての問題の根本は、セットアップ ( beforeEach()) で http サーバーを起動し、ティアダウン ( ) でシャットダウンするMocha テストがあることafterEach()です。ただし、呼び出すだけでserver.close()は完全に終了しないため、その後はエラーhttp.createServer()になることがよくありEADDRINUSEます。close()開いている接続がタイムアウトするまでに非常に長い時間がかかる可能性があるため、完了するのを待つこともできません。

接続を強制的に閉じる方法が必要です。私はこれをクライアント側で行うことができますが、すべてのテスト接続を強制的に閉じますが、サーバー側で、つまり http サーバーにすべてのソケットを強制的に閉じるように指示することをお勧めします。

4

5 に答える 5

44

必要がある

  1. サーバーのイベントにサブスクライブし、connection開いているソケットを配列に追加します
  2. closeイベントをサブスクライブし、閉じたソケットを配列から削除することにより、開いているソケットを追跡します
  3. destroyサーバーを終了する必要がある場合は、残りの開いているすべてのソケットを呼び出します

サーバーを子プロセスで実行し、必要に応じてそのプロセスを終了することもできます。

于 2013-09-18T14:33:39.763 に答える
6

私は通常、これに似たものを使用します:

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 が言うように、単に接続イベントでソケットを収集し、サーバーを閉じるときにそれらを破棄します。

于 2016-02-18T11:20:10.453 に答える
4

最新の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);
于 2018-03-01T11:47:18.863 に答える
2

私のアプローチはthis oneから来ており、基本的に@Ege Özcanが言ったことを行います。

唯一の追加は、ノードが端末から信号を取得していなかったため、サーバーをオフにするルートを設定したことです ('SIGTERM'および'SIGINT')。

さて、ノードは実行時に端末からシグナルを取得していnode whatever.jsましたが、そのタスクをスクリプト ( 'start'package.json のスクリプト -->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();
  }
};
于 2016-05-05T15:44:16.187 に答える