node.js——http原始碼解讀
阿新 • • 發佈:2019-02-14
從慕課網上看到相關node視訊,裡面對http原始碼分析過程做了詳細介紹,其思路和方法很適合於檢視其它原始碼,故記錄下來
以搭建一個web伺服器為栗子
問題: 1、createServer()做了什麼事情 2、回撥函式何時被呼叫 3、request和response是什麼
4、listen()做了哪些事
一、createServer()
進入_http_server.js >>Server()
到此res線找到,res為ServerMessage的例項,也是OutgoingMessage的例項,以下用圖形演示:
>>parser
>>parsers
到_http_common模組中>>onIncoming()何時呼叫
其中parser.incoming就是傳入的req >>parser.incoming
所以req是IncomingMessage的一個例項 至此req線找到,req為IncomingMessage的例項,以下用圖形演示
http.createServer()建立了一個Server例項並監聽request,listen()觸發監聽事件並執行回撥函式。
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是什麼
<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()
request(以下簡稱req)事件何時觸發?(直接在當前目錄下搜尋關鍵字 "emit('request'")【EventEmitter傳送和接收事件】<strong>_http_server.js</strong> function Server(requestListener) { >>>>>>> if (requestListener) { this.addListener('request', requestListener);//如果有回撥函式,對當前例項上新增事件監聽,監聽request,若有request事件觸發,則呼叫回撥 } <<<<<< }
那麼req和res如何生成? 首先在當前函式下>>req發現以作為引數傳入,所以不會再當前函式下新構建 >>res,發現為ServerResponse()的例項並傳入req >>ServerResponse<strong>_http_server.js</strong> function parserOnIncoming(req, shouldKeepAlive) { >>>>>> var res = new ServerResponse(req); self.emit('request',req,res);//呼叫emit方法將request事件傳送給每一個監聽器的例項並傳入req&res,即栗子中回撥函式裡接收的兩個引數 <<<<<< }
<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()觸發監聽事件並執行回撥函式。