这篇文章主要介绍了详解NODEJS的http实现的技术过程以及详细分析,需要的朋友学习参考下吧。
一、前言
目前,HTTP协议是互联网上应用最为广泛的一种网络协议,也是前端er接触最多的一种协议。通过阅读http模块在nodejs中的实现,能够更深入的了解HTTP协议。HTTP协议是基于TCP协议之上的应用层协议,它的实现离不开TCP/IP协议族。而具体到代码实现,http模块依赖于net模块。
如下图所示:在nodejs中,http通过net模块传输数据,得到数据之后依靠HTTP_PARSER对数据进行解析。
二、源码
启动一个HTTP服务
nodejs中启动一个HTTP服务很简单,就是实例化一个Server对象,并且监听某个端口:
const Server = require('./libs/http').Server const server = new Server( function(req, res) { res.writeHead(200) res.end('hello world') }) server.listen(9999)
SERVER类
Server类继承于net.Server,并监听'connection‘事件。
在Server类中,主要做了两件事: 1. 初始化NET模块并建立TCP网络监听 2. 监听自身的request事件
当客户端请求到来的时候,Server实例会首先监听到 'connection' 事件,建立起TCP连接并在connectionListener中暴露出socket对象。接下来,HTTP模块就通过socket对象与客户端进行数据交互。
当一个请求到来后,Server会触发自身的 request 事件,调用 requestListener 方法,即创建Server实例时传入的回调函数。
new Server( function(req, res) { res.writeHead(200) res.end('hello world') })
注: socket对象类似于TCP协议的一个实现,可以通过它与客户端进行数据交互 注: 在 connectionListener 函数中,还初始化了parser实例,并给它绑定了一个 onIncoming 函数 HTTP Parser
整个解析流程在 connectionListener 中进行,socket 通过 'data' 事件获取TCP推入的数据
当socket获取到数据之后,会先对数据进行解析,即:parser.excute(),解析工具是parser。值得说明的是,作者为了实现对 parser 的重用, parser是从一个'FreeList池'中获取的。
... const parser = parsers.alloc() ... connectionListener(socket) { socket.on('data', socketOnData) // TCP推入数据,parser进行解析 function socketOnData(d) { ... const ret = parser.execute(d) ... } }
1、TCP数据到达时, 先执行execute()
2、顺藤摸瓜,我们发现parser.excute 就是 Excute(node_http_parser.cc)。而Excute也只是一个外包而已,具体工作是http_parser_excute(http_parser.c)搞定的。
node_http_parser.cc 只是对 http_parser.c 的一层包装,http_parser.c依靠对外暴露的7个回调周期函数与 node_http_parser.cc 进行数据交互。
3、http_parser.c只有两类回调:HTTP_CB、HTTP_DATA_CB。通过重载的方式,在这两类函数中注册了8个周期函数,如下图:
4、虽然http_parser注册有8个回调函数,但 node_http_parser.cc 对外只暴露出四个周期函数:
parserOnHeaders
parserOnHeadersComplete
parserOnBody
parserOnMessageComplete
5、当 http_parser.c 解析到 on_headers_complete 时,执行HTTP_CB(on_headers_complete)回调函数,如图:
函数内会执行 kOnHeadersComplete 回调函数,即:parserOnHeadersComplete 函数(common.js)
6、此时请求头解析基本完成,接下来创建一个IncomingMessage的实例,然后把请求头数据包装到该实例上。
执行 onIncoming 回调函数,并把得到的IncomingMessage实例作为参数传递进去。
function parserOnHeadersComplete (versionMajor, versionMinor, headers, method, url, statusCode, statusMessage, upgrade, shouldKeepAlive) { ... parser.incoming = new IncomingMessage(parser.socket) parser.incoming.httpVersionMajor = versionMajor parser.incoming.httpVersionMinor = versionMinor parser.incoming.httpVersion = versionMajor + '.' + versionMinor parser.incoming.url = url ... skipBody = parser.onIncoming(parser.incoming, shouldKeepAlive) }
7、 在 parserOnIncoming 中,创建一个ServerResponse实例。
具备了req、res两个实例,接下来触发Server监听的 request 事件。
在 Server 实例化时的,requestListener是作为函数参数对 request 事件进行监听的。
8、回到Server创建时:
const server = new Server( function(req, res) { var data = '' req.on('data', function(chunk){ console.log('chunk: ' + chunk) data += chunk; }) res.writeHead(200) res.end('hello world') })
综上所述,http_parser 解析完 header 之后,就会触发 request 事件。
那body数据放到哪里呢,其实body数据会一直放到流里面,直到用户使用data事件接收数据。也就是说,触发request的时候,body并不会被解析。
三、流程梳理
完整的http请求是这样的: - 客户端发起HTTP请求,首先触发Server端的connection事件,建立TCP链接。
Server接收到connection事件后,建立TCP连接,并暴露出套接字,通过套接字监听'data'事件;初始化http-parser,为后续解析数据备用。
HTTP请求数据到达Server端,parser执行execute方法进行解析,请求头解析成功后,通过回调触发request事件。
至此,我们在Server回调函数中,就接收到了此次http请求的request
四、结语
由于nodejs不少底层库都是C++/C编写的,在阅读、调试的过程中非常不便。我自己在读源码的时候,也只是着重看的JS部分源码。比如,TCP的三次握手、四次挥手,就没深究它的实现细节啦。 以上分析没有涉及到http-body的解析,对于有body的网络请求,实际情况要更加复杂一些,还有一些细节没有完全搞清。等下次总结、分享,我会尽量把漏掉细节都补上。
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上是在NODEJS中详细介绍http实现的详细内容。更多信息请关注PHP中文网其他相关文章!

不同JavaScript引擎在解析和执行JavaScript代码时,效果会有所不同,因为每个引擎的实现原理和优化策略各有差异。1.词法分析:将源码转换为词法单元。2.语法分析:生成抽象语法树。3.优化和编译:通过JIT编译器生成机器码。4.执行:运行机器码。V8引擎通过即时编译和隐藏类优化,SpiderMonkey使用类型推断系统,导致在相同代码上的性能表现不同。

JavaScript在现实世界中的应用包括服务器端编程、移动应用开发和物联网控制:1.通过Node.js实现服务器端编程,适用于高并发请求处理。2.通过ReactNative进行移动应用开发,支持跨平台部署。3.通过Johnny-Five库用于物联网设备控制,适用于硬件交互。

我使用您的日常技术工具构建了功能性的多租户SaaS应用程序(一个Edtech应用程序),您可以做同样的事情。 首先,什么是多租户SaaS应用程序? 多租户SaaS应用程序可让您从唱歌中为多个客户提供服务

本文展示了与许可证确保的后端的前端集成,并使用Next.js构建功能性Edtech SaaS应用程序。 前端获取用户权限以控制UI的可见性并确保API要求遵守角色库

JavaScript是现代Web开发的核心语言,因其多样性和灵活性而广泛应用。1)前端开发:通过DOM操作和现代框架(如React、Vue.js、Angular)构建动态网页和单页面应用。2)服务器端开发:Node.js利用非阻塞I/O模型处理高并发和实时应用。3)移动和桌面应用开发:通过ReactNative和Electron实现跨平台开发,提高开发效率。

JavaScript的最新趋势包括TypeScript的崛起、现代框架和库的流行以及WebAssembly的应用。未来前景涵盖更强大的类型系统、服务器端JavaScript的发展、人工智能和机器学习的扩展以及物联网和边缘计算的潜力。

JavaScript是现代Web开发的基石,它的主要功能包括事件驱动编程、动态内容生成和异步编程。1)事件驱动编程允许网页根据用户操作动态变化。2)动态内容生成使得页面内容可以根据条件调整。3)异步编程确保用户界面不被阻塞。JavaScript广泛应用于网页交互、单页面应用和服务器端开发,极大地提升了用户体验和跨平台开发的灵活性。

Python更适合数据科学和机器学习,JavaScript更适合前端和全栈开发。 1.Python以简洁语法和丰富库生态着称,适用于数据分析和Web开发。 2.JavaScript是前端开发核心,Node.js支持服务器端编程,适用于全栈开发。


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

Atom编辑器mac版下载
最流行的的开源编辑器

ZendStudio 13.5.1 Mac
功能强大的PHP集成开发环境

SublimeText3汉化版
中文版,非常好用

WebStorm Mac版
好用的JavaScript开发工具

VSCode Windows 64位 下载
微软推出的免费、功能强大的一款IDE编辑器