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

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Real_Bird/article/details/52714535

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 name
process.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

小结

  时不我待。

阅读更多

没有更多推荐了,返回首页