node.js——http源码解读

从慕课网上看到相关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事件触发,则调用回调         
  }
  <<<<<<
}


request(以下简称req)事件何时触发?(直接在当前目录下搜索关键字 " emit ( 'request'")【 EventEmitter发送和接收事件
<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的实例并将套接字作为参数传入


>>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()触发监听事件并执行回调函数。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值