从慕课网上看到相关node视频,里面对http源码分析过程做了详细介绍,其思路和方法很适合于查看其它源码,故记录下来
以搭建一个web服务器为栗子
var http = require('http');
http.createServer( function(request ,response){
response.writeHead( 200,{'Content-Type' :'text/plain'});
response.end( 'Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/' );
问题:
1、createServer()做了什么事情
2、回调函数何时被调用
3、request和response是什么
4、listen()做了哪些事
一、createServer()
<strong>http.js</strong>
exports.createServer = function(requestListener) {
return new Server(requestListener); //返回server实例,将回调函数做为参数传入,exports将接口暴露出去
};
>>server
const server = require('_http_server');//引入_http_server私有模块
进入_http_server.js >>Server()
<strong>_http_server.js</strong>
function Server(requestListener) {
>>>>>>>
if (requestListener) {
this.addListener('request', requestListener);//如果有回调函数,对当前实例上添加事件监听,监听request,若有request事件触发,则调用回调
}
<<<<<<
}
<strong>_http_server.js</strong>
function parserOnIncoming(req, shouldKeepAlive) {
>>>>>>
var res = new ServerResponse(req);
self.emit('request',req,res);//调用emit方法将request事件发送给每一个监听器的实例并传入req&res,即栗子中回调函数里接收的两个参数
<<<<<<
}
那么req和res如何生成?
首先在当前函数下>>req发现以作为参数传入,所以不会再当前函数下新构建
>>res,发现为ServerResponse()的实例并传入req
>>
ServerResponse
<strong>_http_server.js</strong>
function ServerResponse(req) {
>>>>>
util.inherits(ServerResponse, OutgoingMessage);//继承自OutgoingMessage,为OM的一个子类,所以回调函数里的res也是OM的一个实例
exports.ServerResponse = ServerResponse;//并暴露接口
<<<<<
}
>>OutgoingMessage
<strong>_http_server.js</strong>
const OutgoingMessage = require('_http_outgoing').OutgoingMessage;//来自_http_outgoing私有模块
<strong>_http_outgoing.js</strong>
function OutgoingMessage() {
Stream.call(this);
>>>>返回一些与服务器有关的属性<<<
}
util.inherits(OutgoingMessage, Stream);//继承自Stream
exports.OutgoingMessage = OutgoingMessage;
到此res线找到,res为ServerMessage的实例,也是OutgoingMessage的实例,以下用图形演示:
再来看req,在parserOnIncoming()作为参数传入,>>parserOnIncoming()在哪里被调用
<strong>_http_server.js</strong>
parser.onIncoming = parserOnIncoming;
>>parser
<strong>_http_server.js</strong>
var parser = parsers.alloc();
>>parsers
<strong>_http_server.js</strong>
const common = require('_http_common');
const parsers = common.parsers;
到_http_common模块中>>onIncoming()何时调用
<strong>_http_common.js</strong>
skipBody = parser.onIncoming(parser.incoming, shouldKeepAlive);
其中parser.incoming就是传入的req
>>parser.incoming
<strong>_http_common.js</strong>
parser.incoming = new IncomingMessage(parser.socket);//IncomingMessage的实例并将套接字作为参数传入
<strong>_http_common.js</strong>
const incoming = require('_http_incoming');
const IncomingMessage = incoming.IncomingMessage;//来自_http_incoming模块
所以req是IncomingMessage的一个实例
至此req线找到,req为IncomingMessage的实例,以下用图形演示
二、listen():
<strong>_http_server.js
</strong>
const net = require('net');
function Server(){
net.Server.call(this, { allowHalfOpen: true });
>>>>>
this.addListener('connection', connectionListener);
<<<<<
}
util.inherits(Server, net.Server);//Server继承net.Server
function connenctListener(socket){
>>>>
function parseronIncoming(req,shouldKeepAlive){
>>>
将request事件发送给监听器
<<<
}
<<<<
}
parseronIncoming()在connectionListener()里定义,connectionListener()在'connection'事件触发时调用,那么connection事件何时触发?
在当前目录下查找事件,没有找到,由‘net.Server.call(this, { allowHalfOpen: true });’>>net.Server发现net为ner.js模块 >>net.js
>>emit('connection
<strong>net.js</strong>
function onconnection(err, clientHandle) {
>>>>
self.emit('connection', socket);
}
conenction在onconnection()里触发
>>onconnenction
<strong>net.js</strong>
Server.prototype._listen2 = function(address, port, addressType, backlog, fd) {
>>>>
this._handle.onconnection = onconnection;
<<<<<
}
onconnection在_listen2里执行
>>_listen2
<strong>net.js</strong>
function listen(self, address, port, addressType, backlog, fd, exclusive) {
>>>>
self._listen2(address, port, addressType, backlog, fd);
<<<<
}
_listen2在listen里被调用
>>listen
<strong>net.js</strong>
Server.prototype.listen = function() {
>>>
<<<
}
listen在Server原型上,又_http_server继承自net,所以在示例代码里的http.createServer()实例上有listen()方法
以下用图形演示
http.createServer()创建了一个Server实例并监听request,listen()触发监听事件并执行回调函数。