http服务端概览

创建server

几行代码搞定

var http = require('http');
var requestListener = function(req, res){
res.end('ok');
};
var server = http.createServer(requestListener);
// var server = new http.Server(requestListener); 跟上面是等价的
server.listen(3000);

获取请求方信息

HTTP版本、HTTP method、headers、url

var http = require('http');

var server = http.createServer(function(req, res){
console.log('客户端请求url:' + req.url);
console.log('http版本:' + req.httpVersion);
console.log('http请求方法:' + req.method); res.end('ok');
}); server.listen(3000);

效果如下:

客户端请求url:/hello
http版本:1.1
http请求方法:GET
http headers:{"host":"127.0.0.1:3000","connection":"keep-alive","cache-control":"max-age=0","upgrade-insecure-requests":"1","user-agent":"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/54.0.2840.71 Safari/537.36","accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8","accept-encoding":"gzip, deflate, sdch, br","accept-language":"zh-CN,zh;q=0.8,en;q=0.6,zh-TW;q=0.4"}

获取get请求参数

var http = require('http');
var url = require('url');
var querystring = require('querystring'); var server = http.createServer(function(req, res){
var urlObj = url.parse(req.url);
var query = urlObj.query;
var queryObj = querystring.parse(query); console.log( JSON.stringify(queryObj) ); res.end('ok');
}); server.listen(3000);

运行如下命令

curl http://127.0.0.1:3000/hello\?nick\=chyingp\&hello\=world

服务端输出如下

{"nick":"chyingp","hello":"world"}

获取post请求参数

代码如下

var http = require('http');
var url = require('url');
var querystring = require('querystring'); var server = http.createServer(function(req, res){ var body = '';
req.on('data', function(thunk){
body += thunk;
}); req.on('end', function(){
console.log( 'post body is: ' + body );
res.end('ok');
});
}); server.listen(3000);

通过curl构造极简post请求

curl -d 'nick=casper&hello=world' http://127.0.0.1:3000

服务端打印如下。注意,在post请求中,不同的Content-type,post body有不小差异,感兴趣的同学可以自己试下。

post body is: nick=casper&hello=world

比如本例中的post请求,HTTP报文大概如下

POST / HTTP/1.1
Host: 127.0.0.1:3000
Content-Type: application/x-www-form-urlencoded
Cache-Control: no-cache nick=casper&hello=world

枯燥的事件

首先,我们来看下有哪些事件

checkContinue、checkExpectation、clientError、close、connect、connection、request、upgrade

error

var http = require('http');
var PORT = 3000;
var noop = function(){}; var svr = http.createServer(noop);
var anotherSvr = http.createServer(noop); anotherSvr.on('error', function(e){
console.error('出错啦!' + e.message);
}); svr.listen(PORT, function(){
anotherSvr.listen(PORT);
});

运行代码,输出如下

出错啦!listen EADDRINUSE :::3000

connect vs connection

两者差别非常大,虽然字眼看着有点像。

  • connect:当客户端的HTTP method为connect时触发。
  • connection:当TCP连接建立时触发,大部分时候可以忽略这个事件(目测模块内部自己用到而已)。此外,可以通过 req.connection 来获取这个socket(从nodejs源码来看,req.socket、req.connection 都指向了这个socket)。此外,socket上的readable事件不会触发(具体原因请看模块内部实现,反正我是还没研究)

大部分时候都不会用到,除非你要开发HTTP代理。当客户端发起 connect 请求时触发(注意绕过了 requestListener)

var http = require('http');
var PORT = 3000; var server = http.createServer(function(req, res){
res.end('ok');
}); // 注意:发起connect请求的例子在 ./httpServerEventConnectClient.js 里
server.on('connect', function(req, socket, head){
console.log('connect事件触发');
socket.end(); // 反正我就只想举个例子,没打算正经处理。。。
}); server.listen(PORT);

request

当有新的连接到来时触发。那跟 connection 有什么区别呢?

好了,keep-alive闪亮登场!在持久化连接的情况下,多个 request 可能对应的是 一个 connection。

先来看下没有keep-alive的场景

var http = require('http');
var PORT = 3000;
var requestIndex = 0;
var connectionIndex = 0; var server = http.createServer(function(req, res){
res.end('ok');
}); server.on('request', function(req, res){
requestIndex++;
console.log('request event: 第'+ requestIndex +'个请求!');
}); server.on('connection', function(req, res){
connectionIndex++;
console.log('connection event: 第'+ connectionIndex +'个请求!');
}); server.listen(PORT);

通过curl连续发送3个请求,看下效果

for i in `seq 1 3`; do curl http://127.0.0.1:3000; done

服务端输出如下

connection event: 第1个请求!
request event: 第1个请求!
connection event: 第2个请求!
request event: 第2个请求!
connection event: 第3个请求!
request event: 第3个请求!

然后,再来看下有keep-alive的场景。用 postman 构造包含 keep-alive 的请求,最终的HTTP请求报文如下

GET / HTTP/1.1
Host: 127.0.0.1:3000
Connection: keep-alive
Cache-Control: no-cache
Postman-Token: 6027fda7-f936-d3ac-e54f-dafcbf5e58ff

连续发送3个请求,服务端打印日志如下

connection event: 第1个请求!
request event: 第1个请求!
request event: 第2个请求!
request event: 第3个请求!

不常用接口

server.close([callback]);

关闭服务器。其实就是 (new net.Server()).close(),停止接受新的连接。 已经连接上的请求会继续处理,当所有连接结束的时候,server 正式关闭,并抛出 close 事件。 一般提供了callback,就不用监听close; 监听了close,就不用添加callback。

其他server.listen()

其实除了 server.listen(PORT) 这种监听方式外,还有以下几种相对不那么常用的监听方式。用到的时候看看文档就行了。

server.listen(handle[, callback]):监听本地文件描述符(fd)(windows不支持),或者server,或者socket server.listen(path[, callback]):监听本地socket,创建一个 UNIX socket server 。 server.listen([port][, hostname][, backlog][, callback])

网络超时 server.setTimeout(msecs, callback)

设置网络连接的超时时间。当超过 msecs 没有响应时,网络就会自动断开。

如果传了 callback,那么当 timeout 发生时,就会将timeout的socket作为参数传给callback。

注意,一般情况下超时的socket会自动销毁。但当你传了callback后,你就需要手动end或者destroy这个socket。

不常用属性

server.listening:是否在监听连接 server.timeout:设置超时时间(毫秒),注意,修改这个值,只会对新建立的连接产生影响。此外,将timeout设置为0,就会禁用自动超时行为。(目测不推荐) server.maxHeadersCount:客户端最多传送的header数量,默认是1000,如果设置为0,则没有限制。(问题:如果超过1000怎么办??)

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

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

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

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

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

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

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

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

    原文:https://github.com/chyingp/nodejs-learning-guide 自己敲代码: ClientRequest概览 当你调用 http.request(options ...

  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. mac上卸载node

    //卸载方法一 有时手贱看到新版本就升级,升级后发现一堆模块不能用了,心情好慢慢调,但也有调不好的时候,只能卸载重装低版本的node了. 我的机器环境如下 1. Mac OSX 10.10.3 2. ...

  2. 杭电 2817 A sequence of numbers【快速幂取模】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2817 解题思路:arithmetic or geometric sequences 是等差数列和等比数 ...

  3. js获取当前位置的地理坐标(经纬度)

    在 freecodecamp 上学习时,碰到获取地理坐标问题.写个笔记纪录下. if(navigator.geolocation) { navigator.geolocation.getCurrent ...

  4. ZBrush曲线功能介绍

    在ZBrush®中曲线功能是一个非常有用的工具.插入笔刷,曲线笔刷,拓扑和许多地方都会用到它.生成曲线的方式有很多种.可以使用重拓扑引导线,可以使用笔触菜单下曲线功能中的框架网格,可以使用ZBrush ...

  5. TF基础4

    模型的存储与加载 TF的API提供了两种方式来存储和加载模型: 1.生成检查点文件,扩展名.ckpt,通过在tf.train.Saver()对象上调用Saver.save()生成.包含权重和其他在程序 ...

  6. Hibernate---criteria的具体使用列子

    方法 说明 Restrictions.eq = Restrictions.allEq 利用Map来进行多个等于的限制 Restrictions.gt > Restrictions.ge > ...

  7. 想说再见不容易,win7最新市占率依然超36%

    微软正在通过努力让Windows 7用户升级至Windows 10,不过从目前的市占率来看,他们还是要加把劲了. 微软正在通过努力让Windows 7用户升级至Windows 10,不过从目前的市占率 ...

  8. 编写python代码获取4k高清壁纸

    Huskiesir最近在研究python爬虫大约俩周了吧,由于比较懒,也没把具体研究的过程与经验写下来,实在是一大憾事.这次直接上干货,代码送给大家: import re import request ...

  9. jquery 将函数作为参数传递

    等待执行函数 这是自己封装的layui的询问框 //------[询问框](parameter:执行函数的参数,f_name:执行函数,msg:提示,time:自动消失时间,btn_arr:按钮组,o ...

  10. 小试牛刀之sort()排序的实现

    受大学室友的鼓动,我也打算利用公众平台来记录自己的前端知识积累,同时呢,自己总结的东西,总归会有局限性,希望小伙伴能给我指点迷津.知识就是一张巨大的网,作为一名摸不清头绪的入学者,唯一能做的事情就是吐 ...