关于 http.Server 类的 close() 方法的疑问◔ ‸◔?

Rachel
  • 361

代码

var http = require('http');
var server = http.createServer().listen(4000);

server.on('close', function () {
  console.log('close event', Date.now());
});

server.on('request', function (req, res) {
  console.log('request', Date.now());
  server.close(function () {
    console.log('server closed!', Date.now());
  });
  res.end('res ok');
})

描述

为什么使用了 server.close(),却不能触发 close 事件?
看了下 HTTP API 描述:

停止服务端接收新的连接。

以及 TCP API 描述:

使服务器停止接收新连接,只保持现存的连接。这个函数是异步的,当所有连接断开时,服务器关闭并且发出'close'事件...

原来 server.close() 只是使服务器停止接收新连接,并没有直接操作关闭服务器。只有当所有连接都断开的时候,服务器才会处于关闭状态并且发射 close 事件。

但是,代码改成延迟调用却可以直接关闭服务器(当然,得在5秒内建立一个HTTP连接)。

var http = require('http');
var server = http.createServer().listen(4000);

server.on('close', function () {
  console.log('close event', Date.now());
});

server.on('request', function (req, res) {
  console.log('request', Date.now());
  res.end('res ok');
})

function closeServer() {
  server.close(function () {
    console.log('server closed!', Date.now());
  });
}

setTimeout(function () {
  closeServer();
}, 5000);

问题

如果按照 API 中的描述,close()方法只是 停止服务端接收新的连接。那么,为什么改为后面这种方式却可以直接关闭服务器?

回复
阅读 3.5k
2 个回答
✓ 已被采纳

api 的描述是正确的。只是你测试的时候理解错了,两种关闭 http 服务最终都会关闭,只是运行逻辑不同。

运行过程

代码 1 会一直等待你建立 http 连接不关闭,直到你请求 1 次 http 连接,然后会在这次请求后的 2 分钟后才关闭 http 服务。

代码 2 会等待你 5 秒钟,如果 5 秒之内你没有建立连接,会直接关闭 http 服务。如果 5 秒之内你请求 1 次 http 连接,然后会在这次请求后的 2 分钟后才关闭 http 服务。

运行过程的原因

原来 server.close() 只是使服务器停止接收新连接,并没有直接操作关闭服务器。只有当所有连接都断开的时候,服务器才会处于关闭状态并且发射 close 事件。 问题在于什么时候算所有连接都断开

当你执行 res.end('res ok'); 的时候,http 连接并没有关闭,因为你的请求的 Connectionkeep-alive,这个时候只是 http 服务返回数据,浏览器渲染页面,http 连接仍然是开启状态,然后如果你 2 分钟内没有新的请求,这次 http 连接才关闭。2 分钟是 http 服务(不是 http 请求)默认的 timeout。

soonfy

关注这个大大的这篇文章:

http://www.html-js.com/articl...

var sockets = [];
server.on("connection",function(socket){
  sockets.push(socket);
  socket.once("close",function(){
     sockets.splice(sockets.indexOf(socket),1);
  });
});

//关闭之前,我们需要手动清理连接池中得socket对象
function closeServer(){
     sockets.forEach(function(socket){
         socket.destroy();
     });
     server.close(function(){
         console.log("close server!");
     });
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏