nodejs中server.close()的使用

我们使用原生的http模块可以方便create一个server出来,但是当我们调用官方api close方法的时候,却发现有时候并不能正确关闭。

先看下api的解释,http的close方法调用的是net模块的close方法:

server.close([callback])#

Stops the server from accepting new connections and keeps existing connections. This function is asynchronous, the server is finally closed when all connections are ended and the server emits a ‘close’ event. Optionally, you can pass a callback to listen for the ‘close’ event.

当我们编写如下代码时,我们看到类似bug一样的现象:

var server = http.createServer(function(req,res){
   res.end();
});

server.listen(7777);
setTimeout(function(){
    server.close(function(){
         console.log("server close");
    });
},3000);

  
  
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
代码laycode - v1.1

看起来毫无问题,运行起来也是毫无问题,3秒后服务器关闭打印log。但是如果在这3秒中你打开了页面,喝喝。那么 server就永远都close不掉了,除非你关闭tab标签,或者整个浏览器。不同系统不同浏览器还不一样。

分析下问题,我加入了下面的2段代码:

var server = http.createServer(function(req,res){
res.writeHead(200,{
    "connection":"close",
    "transfer-encoding":"identity"
});       
res.end();
});

  
  
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
代码laycode - v1.1

可能你认为,默认的nodejs会在header中加入connection keep-alive和transfer-encoding chunked。这2个参数导致的,那么改了这2个参数之后的效果如何?

喝喝,3秒之后,访问页面,返回暂无数据输出,感觉上像是close掉了,但是log依然没有打印出来,关掉tab或者浏览器,log打印。

咦。。。我了个擦,怎么回事呢。最近项目中遇到了这个问题,最后了解到,http协议1.1默认就是长连接,我指定了connection后,应该就及时关闭了,我也不以chunked的方式发送数据,应该都清掉了猜对。。最后,开始看socket的相关知识【麻痹,我还是前端么】发现浏览器与服务器之间的通信,大概是这么个流程。

本地浏览器开始一个socket实例,在本机一个端口上,这个是在http协议上层的,然后发送第一次握手到server,server接收,返回数据给client,然后client发请求说我走啦,拜拜,server再关闭socket这个实例。如果server单方面从server上close了,socket会进入一个close_wait状态。所以么。。客户端不断掉,我们就没办法了么?【具体刚才说的socket知识可见http://blog.9tech.cn/?c=site&m=article&id=81】 或者自己搜索引擎吧,说多了怕误导大家。

所以如果你想及时关闭一个server,或者重启它。你需要自己管理这些socket连接池。在nodejs中需要自己销毁他们。

简单的代码如下:

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!");
     });
}

  
  
  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
代码laycode - v1.1

主要代码就是这些,我们再加入池子之前,记得在socket自己销毁时,排除掉就ok了,这样我们就可以实现及时关闭server,不必等待超时或者客户端主动销毁socket了。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值