server.close()
が2回呼ばれたが、1回目の server.close()
で既に閉じていたため、「Not running error」が起きた。
server.close()
は、サーバを閉じる(新規の接続をしない)が、生きている接続が切断されるまでは完全に閉じない。
Chrome はひとつのコネクションで複数のリクエストを送る。今回の場合は、favicon.ico が2個目のリクエストになっている。chrome://net-internals/#events
でその動きが確認できる。この2個目のリクエスト時に、エラーが発生した。
動きを確認するために、telnet を用いて、HTTP/1.0
でアクセスしてみると、
> telnet 127.0.0.1 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.0
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Fri, 23 Nov 2012 08:13:54 GMT
Connection: close
Hello World
Connection closed by foreign host.
となり、node を実行しているターミナルでも即座にnodeコマンドが終了したことを確認できた。本来、A君が想定した挙動である。
HTTP/1.1
でアクセスしてみると、
> telnet 127.0.0.1 8080
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.1 200 OK
Content-Type: text/plain
Date: Fri, 23 Nov 2012 13:21:14 GMT
Connection: keep-alive
Transfer-Encoding: chunked
c
Hello World
0
となり、サーバは稼働したままであることが確認できる。しばらくすると、nodeコマンドも終了し、telnet側で Connection closed by foreign host.
が示される。
問題点は2つある。
- Chromeがひとつのコネクションで複数のリクエストを送るので、リクエストのたびに起動する
http.createServer()
のコールバックにserver.close()
を記述しているとこのエラーが発生してしまう - Keep Alive な接続なので、
server.close()
しても、すぐにはサーバが終了しない
前者に関しては connection
イベント内に記述しておければ、リクエストのたびに実行されることはない。後者に関しては、レスポンスヘッダーに Connection: close
を記入して対応する。
// hello2.js
var http = require('http');
server = http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain', 'Connection': 'close'});
res.end('Hello World¥n');
});
server.on('connection', function() {
this.close();
});
server.listen(8080, 0, function () {
console.log('Server running at http://localhost:8080/');
});
once() で記述するといいんじゃないだろうかと思いましたが、家に戻らないと確認できないのでメモ。