Node http createServer过程源码解读

示例狂
• 阅读 8278

node的入门就会写这样几行简单的代码,而createServer的过程究竟发生什么

const http = require('http');
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
  res.end('Hello World\n');
});

server.listen(() => {
  console.log(`Server is running `);
});

问题1:request和response是什么

首先在http.js代码中

const Server = exports.Server = server.Server;

exports.createServer = function(requestListener) {
  return new Server(requestListener);
};

createServer做的事情很简单,只是new一个Server的实例,传入回调函数,并返回server

const server = require('_http_server');可以看到server来自_http_server

function Server(requestListener) {
  if (!(this instanceof Server)) return new Server(requestListener);
  net.Server.call(this, { allowHalfOpen: true });
  if (requestListener) {
    this.addListener('request', requestListener);
  }
  this.httpAllowHalfOpen = false;
  this.addListener('connection', connectionListener);
  this.timeout = 2 * 60 * 1000;
  this._pendingResponseData = 0;
}
util.inherits(Server, net.Server);

Server.prototype.setTimeout = function(msecs, callback) {
  this.timeout = msecs;
  if (callback)
    this.on('timeout', callback);
  return this;
};

exports.Server = Server;

Server继承net.Server,且requestListener,作为'request'事件的监听器。

在resOnFinish函数中,self.emit('request', req, res);触发了request事件。

  • res的来源
    var res = new ServerResponse(req);

  • req的来源

    • req来自parserOnIncoming的形参;
      parser.onIncoming = parserOnIncoming.bind(undefined, this, socket, state);而parser来自_http_common的parsers.alloc()。

    • 在方法parserOnHeadersComplete中skipBody = parser.onIncoming(parser.incoming, shouldKeepAlive);传入了request,
      parser.incoming = new IncomingMessage(parser.socket);说明传入的request是IncomingMessage的实例

    • IncomingMessage = require('_http_incoming').IncomingMessage;
      _http_incoming中可以看到util.inherits(IncomingMessage, Stream.Readable);所以IncomingMessage是继承自Stream.Readable

问题2:什么时候执行回调函数

  • connectionListener中有parser.onIncoming = parserOnIncoming.bind(undefined, this, socket, state);

  • 在server的初始化时

    • this.on('request', requestListener);注册request时加上执行回调操作

    • this.on('connection', connectionListener);注册connection的Listener

  • parserOnIncoming方法中 server.emit('request', req, res);发出request;最后在parserOnHeadersComplete方法中调用onIncoming,也就是server里的parserOnIncoming

  • 那么什么时候会发出connection操作呢?

    • 在net.js中的onconnection方法中self.emit('connection', socket);

    • _listen2方法中this._handle.onconnection = onconnection;

    • 在listen里调用listen2self._listen2(address, port, addressType, backlog, fd);

    • Server.prototype.listen = function() 中有对listen方法的调用,也就是说,当server调用listen,会出发connectionListener,进一步触发parserOnIncoming,发出request和response,触发requestListener也就是传入的回调函数

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
美凌格栋栋酱 美凌格栋栋酱
6个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
GoJS API学习
varnode{};node"key""节点Key";node"loc""00";//节点坐标node"text""节点名称";//添加节点通过按钮点击,添加新的节点到画布myDiagram.model.addNodeData(nod
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Stella981 Stella981
3年前
Node.JS vs PHP CLI Server 简单的HTTP服务器性能测试
环境:64位Ubuntu14.04,i53230MPHP5.4.31withZendOPcacheNode.JS0.10.35Node.JS测试varhttprequire('http');http.createServer(function(req,res){   res.
Wesley13 Wesley13
3年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这