Node.js 网络编程

2,463 阅读4分钟

Node 是一个面向网络而生的平台

事件驱动 无阻塞 单线程,具备良好的伸缩性 轻量级

利用Node搭建服务器。ASP ASP.net需要IIS  PHP需要Nginx 或者 Apache  JSP 需要 Tomcat
Node 提供了net dgram http https

构建TCP服务

TCP 传输控制协议 OSI模型【物理层、数据链路层、网络传输层、会话层、表示层、应用层】属于传输层协议
HTTP SMTP IMAP协议都是基于TCP构建
TCP 面向链接的协议,三次握手会话
//创建TCP服务器端
var net = require('net');
var server = net.createServer(function(socket) { //'connection' listener

    //可以用pipe()方法巧妙实现管道操作
    socket.write('hello\r\n');
    socket.pipe(socket);

    console.log('server connected');
    // socket.on('end', function() {
    //     console.log('server disconnected');
    // });
    // socket.on('data', function(){
    //     socket.end('hello\r\n');
    // });
});
server.listen(8124, function() { //'listening' listener
    console.log('server bound');
});
//客户端
var net = require("net");
var client = net.connect({port: 8124}, function(){
    console.log('client connected');
     client.write('world!\r\n');
});
client.on('data', function(data) {
    console.log(data.toString());
    client.end();
});
client.on('end', function() {
    console.log('client disconnected');
    });

TCP 服务的事件

上述代码分为服务器事件和连接事件

1.服务器事件

服务器通过 net.createServer() 创建服务器。 他是 EventEmitter 的一个实例。 他的自定义事件有以下几种
listening: 在调用server.listen() 绑定端口之后  或者 Domain socket  之后触发,简洁的写法为 server.listen(port, listeningListener) 通过第二个参数传入
connection: 客户端套接字连接到服务器的时候触发。简洁的写法为  net.createServer()
close: 当服务器关闭时触发,在调用server.close()之后。 服务器停止接受套接字链接,发散式保存当前存在的链接,等待所有链接都关闭后触发
error: 当服务器发生异常的时候,将会触发这个事件,比如侦听一个使用中的端口  如果不侦听erro人事件,服务器将抛出异常

2.链接事件

服务器可以和多个客户端保持链接,对于每个链接而言典型的可写可读的stream对象。 stream对象可以用于服务器和客户端之间的联系。即可以通过data读取 从一端到另一端发来的数据
也可以通过write()方法从一端想另一段发送数据,,他的自定义事件一下几种:
data: 当一端调用write()发送数据时,另一端会触发data事件,事件的传递的数据即是write()发送的数据。
end: 当一端调用了end() 事件发送FIN数据之后,将触发该事件、
connect: 改事件用于客户端,当套接字与服务器链接成功时候会触发data
drain:当任意一端调用write()发送数据时候,当前这端会触发该事件
error: 抛出异常
close: 当套接字关闭时后触发
timeout: 当一定时间不活跃后,触发该事件,通知用户当前链接已经被闲置了

TCP针对网络中的小数据包有优化策略。

Nagles算法  Node中默认的算法,将小数据包合并一起发送,节省网络带宽

UDP服务

传输音频和视频 DNS服务就是基于他实现的。

###构建HTTP服务

node中http服务简单的实现
var http = require('http');
http.createServer(function(req, res){
    console.log(req.method);  //请求方法
    console.log(req.url);  //  '/'
    console.log(req.httpVersion);  //  1.1
    console.log(req.headers);
    // { host: '127.0.0.1:8000',
    // connection: 'keep-alive',
    // pragma: 'no-cache',
    // 'cache-control': 'no-cache',
    // 'sec-fetch-mode': 'no-cors',
    // 'user-agent':
    //  'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.100 Safari/537.36',
    // accept: 'image/webp,image/apng,image/*,*/*;q=0.8',
    // 'sec-fetch-site': 'same-origin',
    // referer: 'http://127.0.0.1:8000/',
    // 'accept-encoding': 'gzip, deflate, br',
    // 'accept-language': 'zh-CN,zh;q=0.9,en;q=0.8' }
    
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('hello world');

}).listen('8000');
console.log('server is  runing');

HTTP 超文本传输协议

在tcp之上 属于应用层协议
HTTP所做的两件事情,处理HTTP请求和发送HTTP响应
// client.js
var http = require('http');

var options= {
    hostname: '127.0.0.1',   //服务器域名或者ip地址
    port: 1111,     //服务器端口号  默认80
    path: '/',       //请求路径  默认‘/’
    method: 'GET',   //http 默认请求方法 get
    headers:{
        //'Content-Type':'application/x-www-form-urlencoded',
       'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8',
       'Content-Length':10000}
};

var req = http.request(options, function(res) {
    console.log('STATUS ' + res.statusCode);
    console.log('HEADERS ' + JSON.stringify(res.headers));

    res.setEncoding('utf8');
    res.on('data', function(chunk) {
        console.log('数据片段分割======');
        console.log(chunk);
    });

    res.on('end', function() {
        console.log("响应结束======");
   })
})

req.on('error', function(err) {
    console.log(err);
})
req.end();
//错误
//{ Error: connect ECONNREFUSED 127.0.0.1:1111
// at TCPConnectWrap.afterConnect [as oncomplete] (net.js:1097:14)
// errno: 'ECONNREFUSED',
// code: 'ECONNREFUSED',
// syscall: 'connect',
// address: '127.0.0.1',
// port: 1111 }

//正确返回
// STATUS 200
// HEADERS {"content-type":"text/plain","date":"Mon, 19 Aug 2019 06:58:52 GMT","connection":"close","transfer-encoding":"chunked"}
// 数据片段分割======
// hello world
// 响应结束======

构建webSocket服务

webSocket客户端基于事件的编程模型与Node 中自定义事件相差无几
webSocket 实现了客户端与服务器之间的长链接,而Node的事件驱动的方式十分擅长与大量的客户端保持高并发状态
实现双向通讯 采用的是Comet技术 细节是采用长轮询(long-polling)和iframe流