原文:https://github.com/chyingp/nodejs-learning-guide

自己敲代码:

ClientRequest概览

当你调用 http.request(options) 时,会返回 ClientRequest实例,主要用来创建HTTP客户端请求。

在前面的章节里,已经对http模块的的其他方面进行了不少介绍,如http.Server、http.ServerResponse、http.IncomingMessage。

有了前面的基础,详细本文不难理解,本文更多的以例子为主。

简单的GET请求

下面构造了个GET请求,访问 http://id.qq.com/ ,并将返回的网页内容打印在控制台下。

var http = require('http');
var options = {
protocol: 'http:',
hostname: 'id.qq.com',
port: '80',
path: '/',
method: 'GET'
}; var client = http.request(options, function(res){
var data = '';
res.setEncoding('utf8');
res.on('data', function(chunk){
data += chunk;
});
res.on('end', function(){
console.log(data);
});
}); client.end();

当然,也可以用便捷方法 http.get(options) 进行重写

var http = require('http');

http.get('http://id.qq.com/', function(res){
var data = '';
res.setEncoding('utf8');
res.on('data', function(chunk){
data += chunk;
});
res.on('end', function(){
console.log(data);
});
});

简单的post请求

在下面例子中,首先创建了个http server,负责将客户端发送过来的数据回传。

接着,创建客户端POST请求,向服务端发送数据。需要注意的点有:

  1. method 指定为 POST。
  2. headers 里声明了 content-type 为 application/x-www-form-urlencoded。
  3. 数据发送前,用 querystring.stringify(obj) 对传输的对象进行了格式化。
var http = require('http');
var querystring = require('querystring'); var createClientPostRequest = function(){
var options = {
method: 'POST',
protocol: 'http:',
hostname: '127.0.0.1',
port: '3000',
path: '/post',
headers: {
"connection": "keep-alive",
"content-type": "application/x-www-form-urlencoded"
}
}; // 发送给服务端的数据
var postBody = {
nick: 'chyingp'
}; // 创建客户端请求
var client = http.request(options, function(res){
// 最终输出:Server got client data: nick=chyingp
res.pipe(process.stdout);
}); // 发送的报文主体,记得先用 querystring.stringify() 处理下
client.write( querystring.stringify(postBody) );
client.end();
}; // 服务端程序,只是负责回传客户端数据
var server = http.createServer(function(req, res){
res.write('Server got client data: ');
req.pipe(res);
}); server.listen(3000, createClientPostRequest);

各种事件

在官方文档里,http.RequestClient相关的事件共有7个。跟HTTP协议密切相关的有3个,分别是 connect、continue、upgrade,其他4个分别是 abort、aborted、socket、response。

  • 其他:abort、aborted、socket、response
  • 与HTTP协议相关:connect、continue、upgrade

跟HTTP协议相关的会相对复杂些,因为涉及HTTP协议的设计细节。其他3个相对简单。下面分别进行简单的介绍。

response事件

最容易理解的一个,当收到来自服务端的响应时触发,其实跟 http.get(url, cbk) 中的回调是一样的,看下程序运行的打印信息就知道。

var http = require('http');

var url = 'http://id.qq.com/';

var client = http.get(url, function(res){
console.log('1. response event');
}); client.on('response', function(res){
console.log('2. response event');
}); client.end();

打印信息:

1. response event
2. response event

socket事件

当给client分配socket的时候触发,如果熟悉net模块对这个事件应该不陌生。大部分时候并不需要关注这个事件,虽然内部其实挺复杂的。

abort/aborted 事件

这两个事件看着非常像,都是请求中断时触发,差异在于中断的发起方:

  • abort:客户端主动中断请求(第一次调用 client.abort() 时触发)
  • aborted:服务端主动中断请求,且请求已经中断时触发。

continue事件

当收到服务端的响应 100 Continue 时触发。熟悉HTTP协议的同学应该对 100 Continue 有所了解。当客户端向服务端发送首部 Expect: 100-continue ,服务端经过一定的校验后,决定对客户端的后续请求放行,于是返回返回 100 Continue,知会客户端,可以继续发送数据。(request body)

upgrade事件

同样是跟HTTP协议密切相关。当客户端向客户端发起请求时,可以在请求首部里声明 'Connection': 'Upgrade' ,以此要求服务端,将当前连接升级到新的协议。如果服务器同意,那么就升级协议继续通信。这里不打算展开太多细节,直接上官方文档的代码

const http = require('http');

// Create an HTTP server
var srv = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.end('okay');
});
srv.on('upgrade', (req, socket, head) => {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n'); socket.pipe(socket); // echo back
}); // now that server is running
srv.listen(1337, '127.0.0.1', () => { // make a request
var options = {
port: 1337,
hostname: '127.0.0.1',
headers: {
'Connection': 'Upgrade',
'Upgrade': 'websocket'
}
}; var req = http.request(options);
req.end(); req.on('upgrade', (res, socket, upgradeHead) => {
console.log('got upgraded!');
socket.end();
process.exit(0);
});
});

其他

除了上面讲解到的属性、方法、事件外,还有下面方法没有讲到。并不是它们不重要,篇幅有限,后面再展开。

  • client.abort():中断请求;
  • client.setTimeout(timeout):请求超时设置;
  • client.flushHeaders() 及早将请求首部发送出去;
  • client.setSocketKeepAlive():当内部分配 socket 并连接上时,就会内部调用 socket.keepAlive();
  • client.setNoDelay([noDelay]):当内部分配 socket 并连接上时,就会内部调用 socket.setNoDelay();

参考链接

upgrade机制: https://developer.mozilla.org/en-US/docs/Web/HTTP/Protocol_upgrade_mechanism

官方文档: https://nodejs.org/api/http.html#http_class_http_clientrequest

nodejs源码: https://github.com/nodejs/node/blob/master/lib/_http_client.js

NodeJS学习笔记 (7)网络服务-http-client(ok)的更多相关文章

  1. NodeJS学习笔记 (5)网络服务-http-req(ok)

    原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: 概览 本文的重点会放在req这个对象上.前面已经提到,它其实是http.Incom ...

  2. NodeJS学习笔记 (4)网络服务-http(ok)

    原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: http模块概览 大多数nodejs开发者都是冲着开发web server的目的选 ...

  3. NodeJS学习笔记 (9)网络服务-https(ok)

    模块概览 这个模块的重要性,基本不用强调了.在网络安全问题日益严峻的今天,网站采用HTTPS是个必然的趋势. 在nodejs中,提供了 https 这个模块来完成 HTTPS 相关功能.从官方文档来看 ...

  4. NodeJS学习笔记 (8)网络服务-http-server(ok)

    http服务端概览 创建server 几行代码搞定 var http = require('http'); var requestListener = function(req, res){ res. ...

  5. NodeJS学习笔记 (6)网络服务-http-res(ok)

    原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: 概览 http模块四剑客之一的res,应该都不陌生了.一个web服务程序,接受到来 ...

  6. nodejs学习笔记之网络编程

    了解一下OSI七层模型   OSI层 功能 TCP/IP协议 应用层 文件传输,电子邮件,文件服务,虚拟终端  TFTP,HTTP,SNMP,FTP,SMTP,DNS,Telnet 表示层 数据格式化 ...

  7. NodeJS学习笔记 (10)网络TCP-net(ok)

    模块概览 net模块是同样是nodejs的核心模块.在http模块概览里提到,http.Server继承了net.Server,此外,http客户端与http服务端的通信均依赖于socket(net. ...

  8. NodeJS学习笔记 (11)网络UDP-dgram(ok)

    模块概览 dgram模块是对UDP socket的一层封装,相对net模块简单很多,下面看例子. UPD客户端 vs UDP服务端 首先,启动UDP server,监听来自端口33333的请求. se ...

  9. NodeJS学习笔记 (12)网络地址解析-url(ok)

    模块概述 nodejs中,提供了url这个非常实用的模块,用来做URL的解析.在做node服务端的开发时会经常用到.使用很简单,总共只有3个方法. 正式讲解前,各位同学先把下面这个图记在心上(来自no ...

随机推荐

  1. 照片放大软件PhotoZoom怎么用?

    做设计时,难免常常要上网找一些图片素材,但是有时候我们找到图片效果不尽人意,图片风格符合设计要求的的却图片太小,用photoshop放大后,图片的色块像素就出来了,效果极为不理想,这就要我们将图片进行 ...

  2. 关于Number的属性和方法你知晓几分?速来围观!

    1.Number.isFinite() 方法用来检测传入的参数是否是一个有穷数(finite number)返回值为布尔值. 和全局的 isFinite() 函数相比,这个方法不会强制将一个非数值的参 ...

  3. 基于better-scroll封装一个上拉加载下拉刷新组件

    1.起因 上拉加载和下拉刷新在移动端项目中是很常见的需求,遂自己便基于better-scroll封装了一个下拉刷新上拉加载组件. 2.过程 better-scroll是目前比较好用的开源滚动库,提供很 ...

  4. MBR和GPT分区学习

    1.MBR 早期的windows和linux都采用的MBR的方法来处理开机引导程序和分区表,对于linux的MBR分区来讲,0柱面0磁道1扇区用于引导驱动程序,第一扇区有512个字节,前446字节存放 ...

  5. code-reading-notes--libyang-1

    API struct lyd_node * lyd_parse_xml(struct ly_ctx *ctx, struct lyxml_elem **root, int options, ...) ...

  6. js 对象的创建方式和对象的区别

    js一个有三种方法创建对象,这里做一个总结. 1.对象直接量 所谓对象直接量,可以看做是一副映射表,这个方法也是最直接的一个方法,个人比较建议, 1 2 3 4 5 6 7 8 9 10 11 12 ...

  7. java内存管理之内存模型

    1,运行时数据区域 1. 程序计数器 (program counter register) 2. Java虚拟机栈 (jvm stack) 3. 本地方法栈 (native method stack) ...

  8. 洛谷 P2652 同花顺

    P2652 同花顺 题目背景 所谓同花顺,就是指一些扑克牌,它们花色相同,并且数字连续. 题目描述 现在我手里有n张扑克牌,但它们可能并不能凑成同花顺.我现在想知道,最少更换其中的多少张牌,我能让这 ...

  9. Xdoclet + Ant自己主动生成Hibernate配置文件

    在使用Hibernate的时候,过多的Hibernate配置文件是一个让人头疼的问题. 近期接触了Xdoclet这个工具. 它实际上就是一个自己主动代码生成的工具.Xdoclet不能单独执行,必须搭配 ...

  10. unity3d进程通信利用WM_COPYDATE和HOOK

    hello,近期用unity做了进程通信,应该是和c++的PC端实现通信,才開始一头雾水,后来实现了才知道好繁杂......先感谢对我提供帮助的百度,谷歌以及游戏圈的大大们. 在进程通信中非常多方法, ...