这几天在学习node.js中的http模块,对于没有接触过得人真是完全弄不清。昨天通过查看官方文档,查阅各种资料终于理清楚了这几个类在客户端与服务端的请求与响应中扮演了怎样的角色。http模块就是node.js中的核心模块,做的最多的事就是请求和响应,这里只叙述它们是怎样实现这个过程的,只会讲到这几个类里面重要的事件和方法,而不会详细的进行叙述。
http.Server类
http.Server类是用来创建服务器的,http.createServer(requestListener)方法返回的就是new Server(requestListener)。http.Server类有一个request事件,用于监听服务器是否接收到客户端的请求。以最简单服务器代码为例。
var http = require("http");
var server = new http.Server();
server.on('request',function(req,res){
res.writeHead(200,"success",{
"Content-Type":"text/plain"
});
res.write("hello nodejs","utf8");
res.end();
})
server.on('connection',function(){
console.log('hello node!');
});
server.on('close',function(){
console.log('server will close');
});
server.listen(3000);
上述代码搭建了一个简单的服务器,利用request事件监听请求信息,request事件的监听器接收两个参数,其中req为请求内容,res为响应内容。res在github的源码中可以看到req是IncomingMessage类的实例,而var res = new ServerResponse(req),即响应内容为http.ServerResponse的实例。connection事件是在客户端向服务端发送请求,进行TCP连接时触发,网络连接进行TCP三次握手,所以这里会打印3次'hello node!'。close事件是在服务器关闭时触发。http模块提供了一个创建服务器的封装的方法http.createServer()。
const http = require('http');
const server = http.createServer(function(req,res) {
res.writeHead(200,"success",{
"Content-Type":"text/plain"
});
res.write("hello nodejs","utf8");
res.end();
}).listen(3000);
http.createServer()方法创建的时候自动给request事件绑定了监听器,监听器的内容是一样的,其中req为请求内容,是IncomingMessage类的实例,res为响应内容,为http.ServerResponse的实例。这段代码的流程是这样的:用sever.listen()监听端口3000,而函数内部有一个onconnection函数用来查看是否连接,触发connection事件,调用connection事件的监听器connectionListener,在connectionListener中触发request事件,从而调用requestListener。
http.ServerResponse类
http.ServerResponse类是在服务器内部创建的,用于生成服务端响应信息res,并作为第二个参数传递到request事件的监听器中,是一个可写流的子类,将数据写入到响应信息中。http.ServerResponse类定义了close事件,当客户端非正常关闭后触发该事件,同时也定义了res.writeHead()方法以及res.write()方法用于生成响应头的信息以及响应体的信息。
const http = require('http');
const hostname = '127.0.0.1';
const port = 3000;
const server = http.createServer(function(req,res) {
res.writeHead(200,"success",{
"Content-Type":"text/plain"
});
res.write("hello nodejs","utf8");
res.end();
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
writeHead()方法写入响应的状态码,状态描述信息以及响应头,write()向请求体中写入响应信息。每次响应信息完成后都要调用end()方法,该方法会通知服务器,所有响应头和响应主体都已被发送,即服务器将其视为响应已完成。
总结
http.Server类与http.ServerResponse类均为服务器端的对象,前者用来创建服务器,后者用来将数据写入响应信息。服务端有request事件监听请求是否到达,然后用http.ServerResponse类进行响应。
有一点疑惑的是服务端的响应信息res是为http.ServerResponse的实例,而客户端接收到的响应信息是IncomingMessage类的实例,不知道是发生了什么变化,由于官方文档中说过http.IncomingMessage类是由http.Server类和http.ClientRequest类创建的,故这里把这种变化看成暗盒,猜想是服务器在发送响应请求时将响应信息由http.ServerResponse类的实例经过某种变化转换成了http.IncomingMessage类的实例,完成了可写到可读的变化,方便传输。
http模块服务器端涉及的类的关系图如下,:
请求信息是通过http的listen()方法监听的,而request事件是通过http.Server类的connection事件的监听器触发的,这里没有画出来,上面有讲到。