zoukankan      html  css  js  c++  java
  • Node.js开发入门—HelloWorld再分析

    Node.js开发入门(1)我们用http模块实现了一个简单的HelloWorld站点,这次我们再来细致分析下代码。了解很多其它的细节。

    先看看http版本号的HelloWorld代码:

    代码就是这么简单:

    // 引入http模块
    var http = require("http"); 
    
    // 创建server,指定处理client请求的函数
    http.createServer(
        function(request, response) { 
            response.writeHead(200, {"Content-Type": "text/plain"}); 
            response.write("Hello World!"); 
            response.end(); 
        }
    ).listen(8000); 
    
    console.log("Hello World is listening at port 8000");
    

    HelloWorld代码分析

    好啦,从如今開始逐行分析我们的HelloWorld。

    引入模块

    var http = require("http");
    

    require方法用来引入一个模块,參数是模块的名字。比方File System模块。能够这么引入:

    var fs = require("fs");
    

    我们能够把require()方法当做全局方法使用。但实际上它更像属于某个模块的本地方法,它的文档參考这里:https://nodejs.org/api/globals.html

    require方法返回某个模块的实例,比方require(“http”)就返回一个HTTP实例。HTTP实例的參考文档在这里:https://nodejs.org/api/http.html

    我们看到。HTTP模块有一个方法createServer(),就牵涉到我们的第二行代码了。

    创建server

    HTTP模块的createServer()方法,接受一个方法作为參数,原型为:

    http.createServer([requestListener])
    

    requestListener是一个方法,会与http.Server类的request事件关联起来。这样当client请求到达时,requestListener就会被调用。

    requestListener有两个參数,函数原型例如以下:

    function (request, response) { }
    

    第一个參数request的类型是http.IncomingMessage,实现了Readable Stream接口。第二个參数的类型是http.ServerResponse,实现了Writeable Stream接口。Stream的API在这里:https://nodejs.org/api/stream.html

    同一时候,request和response还是EventEmitter。能够发射特定的事件。EventEmitter的API在这里:https://nodejs.org/api/events.html#events_class_events_eventemitter,后面我们会讲怎样使用EventEmitter来发射事件、处理事件。

    再回想一下我们创建server的代码:

    http.createServer(
        function(request, response) { 
            response.writeHead(200, {"Content-Type": "text/plain"}); 
            response.write("Hello World!"); 
            response.end(); 
        }
    ).listen(8000); 
    

    http.createServer返回一个http.Server实例。http.Server的listen方法能够让server监听在某个端口上。演示样例中是8000。

    如你所见,我们提供了一个匿名函数给createServer方法。在这种方法中。我们通过response參数向client回写了“Hello World!”消息。

    分析client请求

    前面我们分析了http.createServer方法,它的參数是一个带两个參数的方法,一个代表了client发过来的请求。一个代表了要回写给client的响应。

    我们来看看request參数。

    request是http.IncomingMessage的实例,通过这个实例,我们能够拿到请求參数。比方HTTP方法、HTTP版本号、url、头部等。详细的API在这里:https://nodejs.org/api/http.html#http_http_incomingmessage

    我们通过改动HelloWorld.js来看看(另存为HelloWorld2.js)。代码例如以下:

    // 引入http模块
    var http = require("http"); 
    
    // 创建server,指定处理client请求的函数
    http.createServer(
        function(request, response) { 
            console.log("method - " + request.method);
            console.log("version - " + request.httpVersion);
            console.log("url - " + request.url);
            response.writeHead(200, {"Content-Type": "text/plain"}); 
            response.write("Hello World!"); 
            response.end(); 
        }
    ).listen(8000); 
    
    console.log("Hello World start listen on port 8000");
    

    如你所见,我使用console这个对象来输出了一些调试信息。打印了HTTP方法、版本号、url等信息。能够运行node HelloWorld2.js,浏览器訪问http://localhost:8000。然后跑到命令行看看输出了什么信息,我这里是这种:

    HTTP REQ

    发送响应给client

    我们简简单单的HelloWorld已经能够发送一些响应数据给client,你在浏览器里能看到“Hello World!”字样。

    这个响应是通过http.ServerResponse的实例response发送给client的。

    http.ServerResponse也是一个Stream。还是一个EventEmitter。我们通过它给客户度返回HTTP状态码、数据、HTTP头部等信息。

    解释一些基本概念。

    HTTP响应由状态行+头部+数据组成。基本结构例如以下:

    |——————————————————|
    |HTTP version|status code|message|
    |—————————————————–|
    | HEADER-NAME-1: value |
    |—————————————————–|
    |HEADER-NAME-2: value |
    |—————————————————–|
    |HEADER-NAME-2: value |
    |—————————————————–|
    |空行(CRLF) |
    |—————————————————–|
    |可选数据(body) |
    |—————————————————–|

    HTTP状态码

    就是200、301、302、403、404之类的数字,由server告诉client这次请求的状态,是成功了呢,还是找不到文件,还是……详细看这里http://kb.cnblogs.com/page/130970/

    在Node.js的HTTP模块,状态行就是通过http.ServerResponse的writeHead方法写给client的。writeHead方法原型例如以下:

    response.writeHead(statusCode[, statusMessage][, headers])
    

    这种方法的第一个參数,就是statusCode,也就是200、403之类的数字,剩下的參数是可选的。最后一个參数是headers,你能够在这里使用JSON对象表示法来写一些HTTP头部,比方:{“Content-Type”:”text/plain”,”Content-Length”:11}。第一个可选參数statusMessage用来指定一个状态描写叙述消息。能够不填写。

    HTTP头部

    头部就是一些key-value对。比方我们在HelloWorld里看到的”Content-Type”,就是用来说明数据类型的头部标签,相应的可能是文本文件、图片、视频、二进制等。

    相似的还有”Content-Length”,用来指定数据长度。

    还有非常多非常多,比方”Date”、”Connection”等。

    详细还是參考前面的链接吧。

    头部还能够使用http.ServerResponse的response.setHeader(name, value)方法来单独设置,一次能够设置一个HTTP头部。

    数据

    头部之后就是数据了。有些状态码,比方200,兴许都会有一些数据。而有些,比方301、404、403、500之类的。多数没有数据。

    数据通过http.ServerResponse的write方法来写回给client,比方这样:

    response.setHeader("Content-Type", "text/html");
    

    这里要提一点,HTTP常见的数据传输编码方式有两种:

    • 设置Content-Length,传输固定长度的数据
    • 设置Transfer-Encoding头部为chunked,分块数据传输

    像我们如今的HelloWorld演示样例,没有设置Content-Length头部。Node.js的HTTP模块就默觉得chunked编码。

    我们使用Chrome浏览器的开发人员工具来查看网络数据。能够非常明白的看到。

    例如以下图所看到的:

    HTTP响应

    我标注出来的三处,都是HelloWorld演示样例传递给浏览器的HTTP头部信息。

    我们通过http.ServerResponse的write方法向client写数据。

    你能够一次写入全部数据。也能够把数据分开来多次写入。

    当要传输的数据量较大时。分多次写入就是比較合理的做法,比方你向client发送大文件。就比較适合分多次写入。也能够利用Node.js的异步特性,获得不错的性能。


    好啦,这次我们略微详细地分析了一遍HelloWorld,下次呢。我们实现一个简单的文件server,会使用到很多其它的Node.js模块和API。

  • 相关阅读:
    [洛谷P2824][题解][HEOI2016/TJOI2016]排序
    [整理]CSP-S2019第一轮试题解析
    [整理]Luogu CSP2020第一轮模拟赛
    [洛谷P4395][题解][BOI2003]Gem 气垫车
    [洛谷P5322][BJOI2019][题解]排兵布阵
    [整理]U S A C O 代 码 小 合 集
    第02组Alpha冲刺 总结
    第02组 Alpha冲刺 (6/6)
    第02组 Alpha冲刺 (5/6)
    第02组 Alpha冲刺 (4/6)
  • 原文地址:https://www.cnblogs.com/gavanwanggw/p/7290698.html
Copyright © 2011-2022 走看看