node创建客户端与服务器端(HTTP)

来源:互联网 发布:仿真软件multisim 编辑:程序博客网 时间:2024/04/29 21:49

Transfer-Encoding: chunked

  在我用telnet登录服务器的时候,服务器返回信息如下。
这里写图片描述
  其中,我们看到这样一条相应–Transfer-Encoding: chunked。Transfer-Encoding头信息的默认值是chunked,主要的原因是Node天生的异步机制,这样响应就可以逐步产生。
  
  发送数据块的方式在涉及文件系统的情况下会非常高效。Web服务器对硬盘上的文件托管服务是很常见的。因为Node允许以数据块的形式往相应中写数据,同时他又允许以数据块的方式读取文件。所以我们就可以用ReadStream文件系统API来实现读取文件。(本文讨论的不是这个)

发送一个简单的HTTP请求

//服务端require( 'http' ).createServer( function ( req, res ) {  res.writeHead( 200 );  res.end( 'hello world' );}).listen( 4000 );//客户端require( 'http' ).request({// 初始化一个新的http.Client Request对象  host: '127.0.0.1',// 一定不能加http  port: 4000,  url: '/',// 随意  mehotd: 'GET'}, function (res) {  var body = '';  res.setEncoding( 'utf-8' );  res.on( 'data', function (chunk) {    body += chunk;  });  res.on( 'end', function () {    console.log( '\n We got: \033[96m' + body + '\033[39m');  });}).end();

  上述代码中,首先调用了一个request方法。此方法用于初始化一个新的http.Client Request对象。注意的是,我们收集的数据是分块的,连接的服务器会返回不同的数据块,只有所有的数据块全部被收集到也能得到完整的相应。当然,也有可能所有的数据在一个data事件中到达了,我们无从而知。
  
  另一个重要问题是:这段代码在chunk都是ascii码数据或者数据量比较少时是没有问题,但如果你的数据是大量中文的话,恭喜你,中枪了,会出现乱码。其原因是两个chunk(Buffer对象)的拼接并不正常,相当于进行了buffer.toString() + buffer.toString()。如果buffer不是完整的,则toString出来后的string是存在问题的(比如一个中文字被截断)。具体可以参见朴灵写得这篇文章:http://cnodejs.org/topic/4faf65852e8fb5bc65113403
  
  在此例中,我们监听end事件,然后将body输出到控制台。另外,我们通过相应对象设置编码为utf-8,因为输出的是文本。
  这里写图片描述
  在上面的例子中,调用完request之后,还需要调用end。
  这是因为,在创建完一个请求之后,在发送给服务器前还可以和request对象进行交互。

querystring

  这是node的一个模块,用来对url参数进行解析(parse)和转换为字符串(stringify)。
  

var qs = require('querystring');console.log( qs.stringify({name: 'real',age:20}) );console.log( qs.stringify({学生: '皖林',age:20}) );console.log( qs.parse( 'name=皖林&age=12' )); 

输出结果为:

name=real&age=20%E5%AD%A6%E7%94%9F=%E7%9A%96%E6%9E%97&age=20{ name: '皖林', age: '12' }

对于要转换为url参数字符串的对象,其键和值都是经过编码的,如果是中文,可以看到明显区别。

客户端

//客户端var  http = require( 'http' ),  qs = require( 'querystring' );function send( theName ) {  var data = qs.stringify({ name:theName });  var request = require( 'http' ).request({// 初始化一个新的http.Client Request对象    host: '127.0.0.1',    port: 3000,    url: '/',// 随意    mehotd: 'POST',    headers: {         'Content-Type':'application/x-www-form-urlencoded',      'Content-Length': data.length,      }   }, function ( res ) {    res.setEncoding( 'utf-8' );//  var body = '';    res.on( 'data', function ( chunk ) { //    body += chunk;    })    res.on( 'end', function () {//     console.log(body);       console.log('\n  \033[90m request complete! \033[39m');       process.stdout.write( '\n your name: ');    });  })  request.end( data ) ;}process.stdout.write( '\n your name: ');// 客户端启动后,输出your nameprocess.stdin.resume();// 等待输入process.stdin.setEncoding( 'utf-8' );// 设置输入流编码process.stdin.on( 'data', function ( name ) {  send( name.replace( '\n', '' ) );});

  有几个需要注意的地方:
  

  • request( {},function(res){} )的第一个参数需要需要显式加上header。否则会报错:Error: socket hang up
  • 尽管我的res.on( ‘data’ , function(){})中没有做任何处理,但这应该是必需的(我尝试过,没有检测data事件的时候,会出问题,问题是无法检测到res.on( ‘end’, funciton(){})事件,我搜索了SO,说是将end换成close或finish有帮助。But,It still doesn’t work for me。我的node版本是v4.4.7。为此,我付出了2个小时的时间,甚至更多。)
  • 分块问题,见上面。

服务端

var qs = require( 'querystring' );require( 'http' ).createServer( function ( req, res ) {  var body = '';  req.on( 'data', function ( chunk ) { //    body += chunk;  })  req.on( 'end', function (){//所有数据接收完毕    res.writeHead( 200 );    res.end( 'Done' );    console.log( '\n got name: \033[90m' + qs.parse( body ).name + '\033[39m');  })}).listen( 3000 );

  服务端同样也是按数据块传输的。这里的res.end( 'Done' );,在我的客户端中可以使用body接收到,即注释的部分代码。

参考

了不起的Node.js

http://cnodejs.org/topic/4fc7789a8be5d070121141cd

小结

  时不我待。

0 0
原创粉丝点击