目录
  1. 1. 深入浅出Node.js学习笔记(七)
    1. 1.1. 网络编程
    2. 1.2. 1. 构建TCP服务
      1. 1.2.1. 1.1 TCP
      2. 1.2.2. 1.2 创建TCP服务器端
      3. 1.2.3. 1.3 TCP服务的事件
    3. 1.3. 2. 构建UDP服务
      1. 1.3.1. 2.1创建UDP套接字
      2. 1.3.2. 2.2 创建UDP服务器端
      3. 1.3.3. 2.3 创建UDP客户端
      4. 1.3.4. 2.4 UDP套接字事件
    4. 1.4. 3. 构建HTTP服务
      1. 1.4.1. 3.1 HTTP
      2. 1.4.2. 3.2 HTTP模块
      3. 1.4.3. 3.3 HTTP客户端
    5. 1.5. 4. 构建WebSocket服务
      1. 1.5.1. 4.1 WebSocket握手
      2. 1.5.2. 4.2 WebSocket数据传输
    6. 1.6. 5. 网络服务与安全
      1. 1.6.1. 5.1 TLS/SSL
      2. 1.6.2. 5.2 TLS服务
      3. 1.6.3. 5.3 HTTPS服务
深入浅出Node.js学习笔记(七)

深入浅出Node.js学习笔记(七)

网络编程

利用Node可以十分方便的搭建网络服务器。

Node提供了net、dgram、http、https等4个模块,分别用于处理TCP、UDP、HTTP、HTTPS,适用于服务器端和客户端。

1. 构建TCP服务

TCP服务在网络应用中十分常见,大多数的应用都是基于TCP搭建而成的。

1.1 TCP

TCP全名为传输控制协议,在OSI模型(物理层、数据链路层、网络层、传输层、会话层、表示层、应用层)中属于传输层协议。

TCP是面向连接的协议,其显著的特征是传输之前需要3次握手形成会话。

只有会话形成后,服务器端和客户端之间才能相互发送数据。在创建会话的过程中,服务器端和客户端分别提供一个套接字,这两个套接字共同形成一个连接。服务器端和客户端则通过套接字实现两者之间的操作。

1.2 创建TCP服务器端

通过net.createServer(listener)即可创建一个TCP服务器,listener是连接事件connection的侦听器。

可以利用Telnet工具作为客户端对创建的服务器进行会话交流。

1.3 TCP服务的事件

TCP服务的事件分为服务器事件和连接事件。

  1. 服务器事件

    对于通过net.createServer()创建的服务器而言,它是一个EventEmitter实例,自定义事件有:

    • listening
    • connection
    • close
    • error
  2. 连接事件

    服务器可以同时与多个客户端保持连接,对于每个连接而言是典型的可写可读Stream对象。Stream对象可以用于服务器端和客户端之间的通信,既可以通过data事件从一端读取另一端发来的数据,也可以通过write()方法从一端向另一端发送数据。自定义事件:

    • data
    • end
    • connect
    • drain
    • error
    • close
    • timeout

    TCP套接字是可写可读的Stream对象,可以利用pipe()方法巧妙地实现管道操作。

    TCP针对网络中的小数据也有一定的优化策略:Nagle算法。

    Nagle算法:

    要求缓冲区的数据达到一定数量或者一定时间后才将其发出,所以小数据包会被Nagle算法合并,因此来优化网络。虽然网络带宽被有效地使用,但是数据有可能被延迟发送。

2. 构建UDP服务

UDP全称为用户数据包协议,与TCP一样属于网络传输层。UDP和TCP最大的不同是UDP不是面向连接的。

2.1创建UDP套接字

创建UDP套接字十分的简单,UDP套接字一旦被创建,既可以作为客户端发送数据,也可以作为服务器端接收数据。

var dgram = rerquire('dgram');
var socket = dgram.createSocket("udp4");

2.2 创建UDP服务器端

想要UDP套接字接收网络信息,只要调用dgram.bind(port,[address])方法对网卡和端口进行绑定即可。

创建UDP服务器端示例:

var dgram = require("dgram");
var server = dgram.createSocket("udp4");
server.on("message", function (msg, rinfo) {
    console.log("server got: " + msg + " from " +
        rinfo.address + ":" + rinfo.port);
});
server.on("listening", function () {
    var address = server.address();
    console.log("server listening " +
        address.address + ":" + address.port);
});
server.bind(41234);

2.3 创建UDP客户端

创建UDP客户端示例:

var dgram = require('dgram');
var message = new Buffer("深入浅出Node.js");
var client = dgram.createSocket("udp4");
client.send(message, 0, message.length, 41234, "localhost", function (err, bytes) {
    client.close();
});

2.4 UDP套接字事件

UDP套接字只是一个EventEmitter的实例。自定义事件:

  • message
  • listening
  • close
  • error

3. 构建HTTP服务

Node提供了基本的http和https模块用于HTTP和HTTPS的封装。

HTTP服务器的实现:

var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n');
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

3.1 HTTP

  1. 初始HTTP

    HTTP的全称是超文本传输协议(HyperText Transfer Protocol)。

    HTTP构建在TCP之上,属于应用层协议。

  2. HTTP报文

    HTTP是基于请求响应式的,以一问一答的方式实现服务。

    HTTP服务只做两件事:处理HTTP请求和发送HTTP响应。

    无论是HTTP请求报文还是HTTP响应报文,报文内容都包含两个部分:报文头和报文体。

3.2 HTTP模块

Node的http模块包含对HTTP处理的封装。

在Node中,HTPP服务继承自TCP服务器(net模块),它能够与多个客户端保持连接,由于其采用事件驱动的形式,并不是为每一个连接创建额外的线程或进程,保持很低的内存占用,所以能够实现高并发。

HTTP服务和TCP服务模型的区别在于,在开启keepalive后,一个TCP会话可以用于多次请求和响应。TCP服务以connection为单元进行服务,HTTP服务以request为单位进行服务。

http模块将连接所用套接字的读写抽象为ServerRequest和ServerResponse对象,分别对应请求和响应操作。

  1. HTTP请求

    对于TCP连接的读操作,http模块将其封装为ServerRequest对象。

  2. HTTP响应

    HTTP响应对象封装了对底层连接的写操作,可以将其看做一个可写的流对象。

    响应结束后,HTTP服务器可能会将当前的连接用于下一个请求,或者关闭连接。

  3. HTTP服务的事件

    HTTP服务也是个EventEmitter实例:

    • connection事件
    • request事件
    • close事件
    • checkContinue事件
    • connect事件
    • upgrade事件
    • clientError事件

3.3 HTTP客户端

HTTP客户端是服务器服务模型的另一部分,处在HTTP的另一端,在整个报文的参与中,报文头和报文体由它产生。

  1. HTTP响应

    HTTP客户端在CLientRequest对象中,它的事件叫做response。

  2. HTTP代理

    http提供的ClientRequest对象是基于TCP层实现的,在keepalive的情况下,一个底层会话连接可以多次用于请求。为了重用TCP连接,http模块包含一个默认的客户端代理对象http。globalAgent.t它对每个服务器端(host+port)创建的连接进行了管理,默认情况下,通过ClientRequest对象对同一个服务器发起的HTTP请求最多可以创建5个连接。它的实质是一个连接池。

    调用HTTP客户端同时对一个服务器发起10次请求时,其实质只有5个请求处于并发状态,后续的请求完成服务后才真正发出。这与浏览器对同一个域名有下载连接数的限制是相同的行为。

  3. HTTP客户端事件

    • response
    • socket
    • upgrade
    • continue

4. 构建WebSocket服务

WebSocket与Node之间的配合堪称完美的理由:

  • WebSocket客户端基于时间的编程模型与Node自定义事件相差无几;
  • WebSocket实现了客户端和服务器端之间的长连接,而Node事件驱动的方式十分擅长于大量的客户端保持高并发连接;

WebSocket与传统HTTP的好处:

  • 客户端与服务器端只建立一个TCP连接,可以使用更少的连接;
  • WebSocket服务器端可以推送数据到客户端,这远比HTTP请求响应模式更加灵活、更加高效;
  • 有更轻量级的协议头,减少数据传送量;

使用WebSocket,网页客户端只需要一个TCP连接即可完成双向通信,在服务器与客户端频繁通信时,无须频繁断开连接和重发请求。

WebSocket与HTTP的区别:

相比HTTP,WebSocket更接近于传输层协议,并没有在HTTP的基础上模拟服务器端的推送,而是在TCP上定义的独立的协议。

WebSocket协议主要分为两个部分:握手和数据传输。

4.1 WebSocket握手

一旦WebSocket握手成功,服务器端与客户端将会呈现对等的效果,都能接收和发送消息。

4.2 WebSocket数据传输

在握手顺利完成后,当前连接不再进行HTTP的交互,而是开始WebSocket的数据帧协议。实现客户端与服务器端的数据交换。

5. 网络服务与安全

5.1 TLS/SSL

  1. 密钥

    TLS/SSL是一个公钥/私钥的结构,它是一个非对称的结构,每个服务器端和客户端都有自己的公私钥。

    公钥用来加密要传输的数据,私钥用来解密接收到的数据。

    公钥和私钥是配对的,通过公钥加密的数据,只有通过私钥才能解密,所以在建立安全传输之前,客户端和服务器端之间需要互换公钥。客户端发送数据时要通过服务器端的公钥进行加密,服务器端发送数据时则需要客户端的公钥进行加密。

    公私钥的非对称加密虽好,但是网络中依然可能存在窃听的情况,典型的例子就是中间人攻击。

    客户端和服务器端在交换公钥的过程中,中间人对客户端扮演服务器端的角色,对服务器端扮演客户端的角色,因此客户端和服务器端几乎感受不到中间人的攻击。

    为了解决中间人攻击,数据传输过程中还需要对得到的公钥进行认证,以确认得到的公钥是出自目标服务器。

  2. 数字证书

    为了确保数据的安全,引入第三方:CA(Certificate Authority,数字证书认证中心)。

    CA的作用是为站点颁发证书,且这个证书中具有CA通过自己的公钥和私钥实现的签名。

    为了得到签名证书,服务器端需要通过自己的私钥生成CSR(Certificate Signing Request,证书签名请求)文件。CA机构将通过这个文件颁发属于该服务器的签名证书,只要通过CA机构就能验证证书是否合法。

5.2 TLS服务

  1. 创建服务器端
  2. TLS客户端

与普通的TCP服务器端和客户端相比,TLS的服务器端和客户端仅仅只在证书的配置上有差别,其余部分基本相同。

5.3 HTTPS服务

HTTPS服务就是工作在TLS/SSL上的HTTP。

  1. 准备证书
  2. 创建HTTPS服务
  3. HTTP客户端
文章作者: BleakNight
文章链接: https://bleaknight95.github.io/2020/01/14/%E6%B7%B1%E5%85%A5%E6%B5%85%E5%87%BANode.js%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%88%E4%B8%83%EF%BC%89/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 BleakNight's Blog
打赏
  • 微信
  • 支付寶

评论