NodeJS服务器退出:完成任务,优雅退出
上一篇文章,我们通过一个简单的例子,学习了NodeJS中对客户端的请求(request)对象的解析和处理,整个文件共享的功能已经完成。但是,纵观整个过程,还有两个地方明显需要改进:
首先,不能共享完毕之后,都通过Ctrl+C来关闭NodeJS服务器。
其次,如果仅仅能向客户端提供d:\ilinkit_logo.png文件的下载,是没有意义的,共享哪个文件,应该可以通过传入的参数来指定。
老规矩,先上一个图:

我们首先来实现退出功能,如果客户端向服务器提交了http://localhost:8000/exit的请求,我们就执行服务器的退出操作。
上一篇文章我们已经能够识别出/xiaohong的请求,所以这个实现起来很简单,代码如下:
var http = require( 'http' );
var fs = require('fs');
var url = require( 'url' ); var file_path = "D:\\ilinkit_logo.png" ;
var file_stream ;
var buffer_box = [] ;
var file_length = 0 ; var file_name = file_path.substr( file_path.lastIndexOf('\\')+1 ); fs.stat( file_path , function ( err , stat ){
if (err) {
if ('ENOENT' == err.code) {
console.log( 'File does not exist...' );
} else {
console.log( 'Read file exception...' );
}
} else {
file_stream = fs.createReadStream( file_path );
file_stream.on( 'data' , function( chunk ){
buffer_box.push( chunk ) ;
file_length += chunk.length ;
} );
file_stream.on( 'end' , function( ){
console.log( "文件读取完毕" );
} );
file_stream.on('error', function(err){
console.log( "文件读取失败!" );
}); var server =http.createServer( function ( request ,response ){
var h_name = request.headers.host ;
var h_path = url.parse( request.url ).pathname ; if( h_path === '/xiaohong' ){
response.setHeader( 'Content-Type' , 'application/octet-stream' );
response.setHeader( 'Content-Disposition' , 'attachment; filename=' + encodeURIComponent(file_name) ); for( var buffer_index = 0 ; buffer_index<buffer_box.length ; buffer_index++ )
{
response.write( buffer_box[buffer_index] );
}
response.end();
}
else if( h_name === 'localhost:8000' && h_path === '/exit' ){
response.end('Bye!');
server.close() ;
console.log( 'Bye!' );
}
else{
response.end( 'Hello, iLinkIT' );
} } );
server.listen( 8000 );
console.log( 'HTTP服务器启动中,端口:8000.....' ); }//end else,读取文件没有发生错误
});
关键的代码解析如下:
第33行,我们通过request对象获取客户端请求的主机及端口内容。
第46行~第50行,我们判断客户端提交的请求信息,如果是http://localhost:8000/exit,则调用server.close()关闭服务器。为什么要判断是不是localhost提交的请求?因为我们希望仅仅在服务器本地提交的请求才能关闭NodeJS服务器。
验证方式如下:
1. 启动服务器:打开命令行,进入js脚本所在的位置,执行:node h_ilinkit_1.js。
2. 打开浏览器,输入:http://localhost:8000,显示如下:

说明当前服务器启动正常。
3. 打开浏览器,输入:http://localhost:8000/exit。

提示NodeJS服务器已经关闭,我们把浏览器关闭之后,发现服务器已经正常退出,如下所示。

这样,我们就没必要每次为了退出服务器,都去按Ctrl + C了。
通过请求退出服务器就介绍到这里,接下来我们再看一下,如果在启动NodeJS服务器的时候,给它传入参数。对应到我们爱莲(iLinkIT)的场景,希望能够将要共享的文件的路径作为参数传递给NodeJS服务器,服务器根据传入的文件路径读取数据到缓冲区,接受客户端的响应。
代码如下:
var http = require( 'http' );
var fs = require('fs');
var url = require( 'url' ); var args = process.argv.splice( 2 );
var file_path = args.join( '' ) ;
var file_stream ;
var buffer_box = [] ;
var file_length = 0 ; var file_name = file_path.substr( file_path.lastIndexOf('\\')+1 ); fs.stat( file_path , function ( err , stat ){
if (err) {
if ('ENOENT' == err.code) {
console.log( 'File does not exist...' );
} else {
console.log( 'Read file exception...' );
}
} else {
file_stream = fs.createReadStream( file_path );
file_stream.on( 'data' , function( chunk ){
buffer_box.push( chunk ) ;
file_length += chunk.length ;
} );
file_stream.on( 'end' , function( ){
console.log( "文件读取完毕" );
} );
file_stream.on('error', function(err){
console.log( "文件读取失败!" );
}); var server =http.createServer( function ( request ,response ){
var h_name = request.headers.host ;
var h_path = url.parse( request.url ).pathname ; if( h_path === '/xiaohong' ){
response.setHeader( 'Content-Type' , 'application/octet-stream' );
response.setHeader( 'Content-Disposition' , 'attachment; filename=' + encodeURIComponent(file_name) ); for( var buffer_index = 0 ; buffer_index<buffer_box.length ; buffer_index++ )
{
response.write( buffer_box[buffer_index] );
}
response.end();
}
else if( h_name === 'localhost:8000' && h_path === '/exit' ){
response.end('Bye!');
server.close() ;
console.log( 'Bye!' );
}
else{
response.end( 'Hello, iLinkIT' );
} } );
server.listen( 8000 );
console.log( 'HTTP服务器启动中,端口:8000.....' ); }//end else,读取文件没有发生错误
});
关键代码解析如下:
第5行,通过process.argv.splice( 2 )获得了传入的命令行参数。
之前我们启动NodeJS服务器的命令为:node h_ilinkit_1.js,而要传入参数之后,执行的命令为node h_ilinkit_2.js d:\ilinkit_logo.rar,
process.argv会将输入命令行的所有的内容都获取到,包括node h_ilinkit_2.js部分,我们通过调用splice( 2 ),获得传入的第3个参数的内容,将前面的两个字符串剔除掉。
第6行,将输入命令行的内容中,除了node h_ilinkit_2.js之外的内容合并在一起,作为文件路径。
验证方式如下:
1. 启动服务器:打开命令行,进入js脚本所在的位置,执行:node h_ilinkit_2.js d:\ilinkit_logo.rar,如下图所示:

3. 打开浏览器,输入:http://localhost:8000/xiaohong,显示如下:

可见,我们已经实现了通过命令行传入参数的功能,因为我们传入的是d:\ilinkit_logo.rar,所以,客户端提交请求后,下载到的文件也是ilinkit_logo.rar。
简单回顾一下:
1. 借助NodeJS的服务器响应机制,通过给服务器提交/exit的请求,实现服务器的退出操作。
2. 通过在启动NodeJS时,向服务器传入共享文件的路径,实现共享文件的自定义,这样,想共享哪个文件,就可以共享哪个文件。
关于通过爱莲(iLinkIT)这个小项目讲解NodeJS的特性的文章,到此已经全部结束,不知道您是否已经对NodeJS产生爱恋^_^?更深入的了解NodeJS,推荐您根据业务需要,找专门的专著来阅读,另外,泡NodeJS社区论坛,也是一个扩大认识,解决问题的好办法,没错,就是这个社区:https://cnodejs.org/
感谢您的捧场,晚安^_^~~
-----------------------爱莲(iLinkIT)系列文章------------------------------------------
NodeJS服务器退出:完成任务,优雅退出的更多相关文章
- Node 出现 uncaughtException 之后的优雅退出方案
Node 的异步特性是它最大的魅力,但是在带来便利的同时也带来了不少麻烦和坑,错误捕获就是一个.由于 Node 的异步特性,导致我们无法使用 try/catch 来捕获回调函数中的异常,例如: try ...
- .NET Worker Service 作为 Windows 服务运行及优雅退出改进
上一篇文章我们了解了如何为 Worker Service 添加 Serilog 日志记录,今天我接着介绍一下如何将 Worker Service 作为 Windows 服务运行. 我曾经在前面一篇文章 ...
- 正确使用‘trap指令’实现Docker优雅退出
一般应用(比如mariadb)都会有一个退出命令,用户使用类似systemctl stop ****.service方法,停止其服务时,systemd会调用其配置文件注册的退出命令,该命令执行清理资源 ...
- golang channel详解和协程优雅退出
非缓冲chan,读写对称 非缓冲channel,要求一端读取,一端写入.channel大小为零,所以读写操作一定要匹配. func main() { nochan := make(chan int) ...
- golang中使用Shutdown特性对http服务进行优雅退出使用总结
golang 程序启动一个 http 服务时,若服务被意外终止或中断,会让现有请求连接突然中断,未处理完成的任务也会出现不可预知的错误,这样即会造成服务硬终止:为了解决硬终止问题我们希望服务中断或退出 ...
- .NET Worker Service 如何优雅退出
上一篇文章中我们了解了 .NET Worker Service 的入门知识[1],今天我们接着介绍一下如何优雅地关闭和退出 Worker Service. Worker 类 从上一篇文章中,我们已经知 ...
- 优雅退出在Golang中的实现
背景 为什么需要优雅关停 在Linux下运行我们的go程序,通常有这样2种方式: 前台启动.打开终端,在终端中直接启动某个进程,此时终端被阻塞,按CTRL+C退出程序,可以输入其他命令,关闭终端后程序 ...
- NodeJS服务器:一行代码 = 一个的HTTP服务器
从这一篇开始,我们进入技术讲解的话题,逐步实现用NodeJS实现文件的传送共享服务. 前文我们讲过,NodeJS是最擅长做网络服务器的,今天我们就来用NodeJS做一个最简单的服务器. 先看一幅图: ...
- pm2命令,端口查询,mongodb服务启动,nginx服务启动,n模块的使用,搭建nodejs服务器环境,搭建oracledb服务器环境 linux的环境搭建
pm2命令 pm2 ls //查询pm2 启动的列表 pm2 start app.js //启动文件 pm2 restart app //重启项目 pm2 logs app //监控项目执行日志打印 ...
随机推荐
- hadoop namenode又一次格式化以后hbase的hmaster进程启动后立即消失
hadoop的 namenode又一次格式化以后.重新启动hbase.发现它的hmaster进程启动后立即消失,查看一大堆日志,最后在zookeeper的日志里发现例如以下问题 Unable to r ...
- VS2012开发ActiveX插件 尝试1
今天闲来无聊研究了下 ActiveX插件开发,以前一直以为很牛逼,然后发现还是比较简单的东西.. 首先: 在开始前 准备好 VS12开发工具,cabarc.exe 工具(注:这是 用来 将文件打包成c ...
- ResultSet转成java类对象
在做web开发时遇到一个事情: 需要从mysql数据表中查询数据并遍历查询结果 这样最简单的方式是:查询到结果根据表中字段列表的顺序来一个个获取字段,但这样需要记住字段的顺序,操作起来不是那么方便.因 ...
- C# - 函数参数的传递
近段时间,有几个刚刚开始学习C#语言的爱好者问我:C#中的函数,其参数的传递,按值传递和按引用传递有什么区别.针对这一问题,我简单写了个示例程序,用以讲解,希望我没有把他们绕晕.因为,常听别人说起:“ ...
- 04.URL路径访问与模块控制器之间的关系
<?php //初使化,进行加载. //通过这个英文名来了解,他是定义的与thinkphp有关的核心框架文件目录路径 //他可以通过这一个常量,在以后运行的时候都去找这个路径,确保在运行过程当, ...
- Nagios在Ubuntu server上的安装配置
首先我参看的是Nagios的官方文档,Nagios – Installing Nagios Core From Source——The Industry Standard in IT Infrastr ...
- 第1章 游戏之乐——NIM(3)两堆石头的游戏
NIM(3)两堆石头的游戏 1. 问题描述 假设有两堆石头,有两个玩家会根据如下的规则轮流取石头:每人每次可以从两堆石头中各取出数量相等的石头,或者仅从一堆石头中取出任意数量的石头:最后把剩下的石头一 ...
- linux epoll模型
原文:http://yjtjh.blog.51cto.com/1060831/294119 Linux I/O多路复用技术在比较多的TCP网络服务器中有使用,即比较多的用到select函数.Linux ...
- python中文处理之encode/decode函数
python中文处理相信迷惑过不少同学.下面说说python2/3的encode和decode函数. python2中,使用decode()和encode()来进行解码和编码,以unicode类型作为 ...
- cocos2d-x lua table与json的转换
cocos2d-x lua table与json的转换 version: cocos2d-x 3.6 1.引入json库 require("src/cocos/cocos2d/json&qu ...