我们使用原生的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一样的现象:
看起来毫无问题,运行起来也是毫无问题,3秒后服务器关闭打印log。但是如果在这3秒中你打开了页面,喝喝。那么 server就永远都close不掉了,除非你关闭tab标签,或者整个浏览器。不同系统不同浏览器还不一样。
分析下问题,我加入了下面的2段代码:
可能你认为,默认的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中需要自己销毁他们。
简单的代码如下:
主要代码就是这些,我们再加入池子之前,记得在socket自己销毁时,排除掉就ok了,这样我们就可以实现及时关闭server,不必等待超时或者客户端主动销毁socket了。