NodeJS服务器退出:完成任务,优雅退出

摘要:
因为我们只想关闭NodeJS服务器上本地提交的请求。它提示NodeJS服务器已关闭。关闭浏览器后,我们发现服务器已正常退出,如下所示。这就是通过请求退出服务器的全部内容。接下来,让我们看看在NodeJS服务器启动时如何将参数传递给它。与我们的Ailian场景相对应,我们希望可以将要共享的文件的路径作为参数传递给NodeJS服务器。服务器根据传入文件路径将数据读取到缓冲区,并接受来自客户端的响应。

上一篇文章,我们通过一个简单的例子,学习了NodeJS中对客户端的请求(request)对象的解析和处理,整个文件共享的功能已经完成。但是,纵观整个过程,还有两个地方明显需要改进:

首先,不能共享完毕之后,都通过Ctrl+C来关闭NodeJS服务器。

其次,如果仅仅能向客户端提供d:ilinkit_logo.png文件的下载,是没有意义的,共享哪个文件,应该可以通过传入的参数来指定。

老规矩,先上一个图:

NodeJS服务器退出:完成任务,优雅退出第1张

我们首先来实现退出功能,如果客户端向服务器提交了http://localhost:8000/exit的请求,我们就执行服务器的退出操作。

上一篇文章我们已经能够识别出/xiaohong的请求,所以这个实现起来很简单,代码如下:

 1 var http = require( 'http' );
 2 var fs = require('fs');
 3 var url = require( 'url' );
 4 
 5 var file_path = "D:\ilinkit_logo.png" ;
 6 var file_stream ;
 7 var buffer_box = [] ;
 8 var file_length = 0 ; 
 9 
10 var file_name = file_path.substr( file_path.lastIndexOf('\')+1 );
11 
12 fs.stat( file_path , function ( err , stat ){
13             if (err) {
14                 if ('ENOENT' == err.code) {
15                     console.log( 'File does not exist...' );
16                 } else {
17                     console.log( 'Read file exception...' );
18                 }
19             } else {
20                 file_stream = fs.createReadStream( file_path );      
21                 file_stream.on( 'data' , function( chunk ){
22                     buffer_box.push( chunk ) ;
23                     file_length += chunk.length ;
24                 } ); 
25                 file_stream.on( 'end' , function(  ){
26                     console.log( "文件读取完毕" );
27                 } );
28                 file_stream.on('error', function(err){
29                     console.log( "文件读取失败!" );
30                 }); 
31                 
32                 var server =http.createServer( function ( request ,response ){
33                   var h_name = request.headers.host ;
34                   var h_path = url.parse( request.url ).pathname ;
35                   
36                   if( h_path === '/xiaohong' ){
37                     response.setHeader( 'Content-Type' , 'application/octet-stream' );
38                     response.setHeader( 'Content-Disposition' , 'attachment; filename=' + encodeURIComponent(file_name) );
39                     
40                     for( var buffer_index = 0 ; buffer_index<buffer_box.length ; buffer_index++ )
41                     {
42                         response.write( buffer_box[buffer_index] );
43                     }
44                     response.end();
45                    }
46                    else if( h_name === 'localhost:8000' && h_path === '/exit' ){
47                     response.end('Bye!');
48                     server.close() ; 
49                     console.log( 'Bye!' );
50                    }
51                    else{
52                     response.end( 'Hello, iLinkIT' );    
53                    }
54                    
55                 } );
56                 server.listen( 8000 );
57                 console.log( 'HTTP服务器启动中,端口:8000.....' );
58                 
59             }//end else,读取文件没有发生错误
60 });                 

关键的代码解析如下:

第33行,我们通过request对象获取客户端请求的主机及端口内容。

第46行~第50行,我们判断客户端提交的请求信息,如果是http://localhost:8000/exit,则调用server.close()关闭服务器。为什么要判断是不是localhost提交的请求?因为我们希望仅仅在服务器本地提交的请求才能关闭NodeJS服务器。

验证方式如下:

1. 启动服务器:打开命令行,进入js脚本所在的位置,执行:node h_ilinkit_1.js

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

NodeJS服务器退出:完成任务,优雅退出第2张

说明当前服务器启动正常。

3. 打开浏览器,输入:http://localhost:8000/exit。

NodeJS服务器退出:完成任务,优雅退出第3张

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

NodeJS服务器退出:完成任务,优雅退出第4张

这样,我们就没必要每次为了退出服务器,都去按Ctrl + C了。

通过请求退出服务器就介绍到这里,接下来我们再看一下,如果在启动NodeJS服务器的时候,给它传入参数。对应到我们爱莲(iLinkIT)的场景,希望能够将要共享的文件的路径作为参数传递给NodeJS服务器,服务器根据传入的文件路径读取数据到缓冲区,接受客户端的响应。

代码如下:

 1 var http = require( 'http' );
 2 var fs = require('fs');
 3 var url = require( 'url' );
 4 
 5 var args = process.argv.splice( 2 );
 6 var file_path = args.join( '' ) ;
 7 var file_stream ;
 8 var buffer_box = [] ;
 9 var file_length = 0 ; 
10 
11 var file_name = file_path.substr( file_path.lastIndexOf('\')+1 );
12 
13 fs.stat( file_path , function ( err , stat ){
14             if (err) {
15                 if ('ENOENT' == err.code) {
16                     console.log( 'File does not exist...' );
17                 } else {
18                     console.log( 'Read file exception...' );
19                 }
20             } else {
21                 file_stream = fs.createReadStream( file_path );      
22                 file_stream.on( 'data' , function( chunk ){
23                     buffer_box.push( chunk ) ;
24                     file_length += chunk.length ;
25                 } ); 
26                 file_stream.on( 'end' , function(  ){
27                     console.log( "文件读取完毕" );
28                 } );
29                 file_stream.on('error', function(err){
30                     console.log( "文件读取失败!" );
31                 }); 
32                 
33                 var server =http.createServer( function ( request ,response ){
34                   var h_name = request.headers.host ;
35                   var h_path = url.parse( request.url ).pathname ;
36                   
37                   if( h_path === '/xiaohong' ){
38                     response.setHeader( 'Content-Type' , 'application/octet-stream' );
39                     response.setHeader( 'Content-Disposition' , 'attachment; filename=' + encodeURIComponent(file_name) );
40                     
41                     for( var buffer_index = 0 ; buffer_index<buffer_box.length ; buffer_index++ )
42                     {
43                         response.write( buffer_box[buffer_index] );
44                     }
45                     response.end();
46                    }
47                    else if( h_name === 'localhost:8000' && h_path === '/exit' ){
48                     response.end('Bye!');
49                     server.close() ; 
50                     console.log( 'Bye!' );
51                    }
52                    else{
53                     response.end( 'Hello, iLinkIT' );    
54                    }
55                    
56                 } );
57                 server.listen( 8000 );
58                 console.log( 'HTTP服务器启动中,端口:8000.....' );
59                 
60             }//end else,读取文件没有发生错误
61 });                 

关键代码解析如下:

第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,如下图所示:

NodeJS服务器退出:完成任务,优雅退出第5张

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

NodeJS服务器退出:完成任务,优雅退出第6张

可见,我们已经实现了通过命令行传入参数的功能,因为我们传入的是d:ilinkit_logo.rar,所以,客户端提交请求后,下载到的文件也是ilinkit_logo.rar。

简单回顾一下:

1. 借助NodeJS的服务器响应机制,通过给服务器提交/exit的请求,实现服务器的退出操作。

2. 通过在启动NodeJS时,向服务器传入共享文件的路径,实现共享文件的自定义,这样,想共享哪个文件,就可以共享哪个文件。

关于通过爱莲(iLinkIT)这个小项目讲解NodeJS的特性的文章,到此已经全部结束,不知道您是否已经对NodeJS产生爱恋^_^?更深入的了解NodeJS,推荐您根据业务需要,找专门的专著来阅读,另外,泡NodeJS社区论坛,也是一个扩大认识,解决问题的好办法,没错,就是这个社区:https://cnodejs.org/

感谢您的捧场,晚安^_^~~

-----------------------爱莲(iLinkIT)系列文章------------------------------------------

 缘起爱莲:我要的,现在就要!

爱莲(iLinkIT)的架构与原理

遇见NodeJS:JavaScript的贵人

NodeJS服务器:一行代码 = 一个的HTTP服务器

NodeJS文件读取:感恩常在--抓把糖果,愉悦客人

NodeJS缓存机制:畅销货,就多囤一点呗

NodeJS安全设计:好吃的草莓味糖果,只给好朋友小红

NodeJS服务器退出:完成任务,优雅退出

免责声明:文章转载自《NodeJS服务器退出:完成任务,优雅退出》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇bootstrap的datetimepicker使用(1.将默认的英文设置为中文2.选择日月年的时候记录之前的操作)C# windows media player详细用法(最全面)下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

python爬虫学习笔记(二十五)-Scrapy框架 Middleware

1. Spider 下载中间件(Middleware) Spider 中间件(Middleware) 下载器中间件是介入到 Scrapy 的 spider 处理机制的钩子框架,您可以添加代码来处理发送给 Spiders 的 response 及 spider 产生的 item 和 request 2. 激活一个下载DOWNLOADER_MIDDLEWARE...

angularJS实现无刷新文件下载

1 $scope.getExcel = function() { 2 $http.post("/production/statistics/export", { 3 storeId: $scope.$parent.currStore.storeId, 4 date: $scope.$parent.ledgerDat...

js 获取地址第1个斜杠后的内容或地址前一部分

var value = "https://www.baidu.com/20210922/95b22ab5034b2d0f.jpg";const str = value.split("https://"); //https://进行分割, const index = str[1].indexOf("/")+1; //indexOf 获取第一个斜杠的索引,co...

AS3的数据类型和定义

AS3的数据类型分: 基元数据类型:Boolean  int(整数)  Number(长的浮点数)  unit(很大的正整数)  String 复杂数据类型:Arrary  Date  Error  Function  RegExp  XML  XMLList 声明变量的格式: var 变量名:数据类型=值; var i:int=2;...

Http 持久连接与 HttpClient 连接池

一、背景 HTTP协议是无状态的协议,即每一次请求都是互相独立的。因此它的最初实现是,每一个http请求都会打开一个tcp socket连接,当交互完毕后会关闭这个连接。 HTTP协议是全双工的协议,所以建立连接与断开连接是要经过三次握手与四次挥手的。显然在这种设计中,每次发送Http请求都会消耗很多的额外资源,即连接的建立与销毁。 于是,HTTP协议的也...

远程连接ubuntu的MongoDB遇到的坑

首先连接不上,先查看云服务器上的安全组是否添加了对应的端口 如果打开了,那么久查看MongoDB是否允许远程连接 # mongod.conf # for documentation of all options, see: # http://docs.mongodb.org/manual/reference/configuration-optio...