一,开篇分析

从今天开始,我们来深入具体的模块学习,这篇文章是这个系列(大熊君大话NodeJS)文章的第三篇,前两篇主要是以理论为主,相信大家在前两篇的学习中,

对NodeJS也有一个基本的认识,没事!!!趁热打铁,让我们继续将NodeJS进行到底,好了废话不多说,直接进入今天的主题 “Net模块” ,那么”Net“应该如何理解那?

它是做什么用的那?(Net模块可用于创建Socket服务器或Socket客户端。 NodeJS 的数据通信,最基础的两个模块是 Net 和 Http,前者是基于 Tcp 的封装,后者本质还是 Tcp 层,只不过做了比较多的数据封装,我们视为表现层)。

这里参考一下NodeJS “http.js” 中的源码:

从图中不难看出 HttpServer继承了Net类,具有了相关的通信能力,做了比较多的数据封装,我们视为更高级的表现层。

 扩展知识(以下是“inherits”的源码):

 1 exports.inherits = function(ctor, superCtor) {
 2   ctor.super_ = superCtor;
 3   ctor.prototype = Object.create(superCtor.prototype, {
 4     constructor: {
 5       value: ctor,
 6       enumerable: false,
 7       writable: true,
 8       configurable: true
 9     }
10   });
11 };

功能是实现继承复用。

刚才做了一个简要的概述,里面有一些常用的概念,这里做个简短的概念普及介绍:

  (1),TCP/IP------TPC/IP协议是传输层协议,主要解决数据如何在网络中传输。

  (2),Socket------socket则是对TCP/IP协议的封装和应用(程序层面)。

  (3),Http------HTTP是应用层协议,主要解决如何包装数据。

  (4),网络七层模型------物理层、数据链路层、网络层、传输层、会话层、表示层和应用层。

  总结一下:Socket是对TCP/IP协议的封装,Socket本身并不是协议,而是一个调用接口(API)。

  从而形成了我们知道的一些最基本的函数接口,比如Create、Listen、Connect、Accept、Send、Read和Write等等。

  TCP/IP只是一个协议栈,就像操作系统的运行机制一样,必须要具体实现,同时还要提供对外的操作接口

  实际上,传输层的TCP是基于网络层的IP协议的,而应用层的HTTP协议又是基于传输层的TCP协议的,而Socket本身不算是协议,就像上面所说,它只是提供了一个针对TCP或者UDP编程的接口。

二,体验一把

好了,概念我们也有了,来个例子:

1,建立server.js

 1 var net = require('net') ;
 2 var server = net.createServer(function(c) { // Connection监听器
 3   console.log("服务器已连接") ;
 4   c.on("end", function() {
 5     console.log("服务器已断开") ;
 6   }) ;
 7   c.write("Hello,Bigbear !\r\n") ;
 8   c.pipe(c) ;
 9 }) ;
10 server.listen(8124, function() { // Listening监听器
11   console.log("服务器已绑定") ;
12 }) ;

2,建立client.js

 1 var net = require('net') ;
 2 var client = net.connect({
 3     port: 8124
 4 },function(){ // connect监听器
 5   console.log("客户端已连接") ;
 6   client.write('Hello,Baby !\r\n') ;
 7 });
 8 client.on("data", function(data) {
 9   console.log(data.toString()) ;
10   client.end() ;
11 });
12 client.on("end", function(){
13   console.log("客户端断开连接") ;
14 }) ;

分析一下:

服务端------net.createServer 创建一个 TCP 服务,这个服务绑定(server.listen)在 8124 这个端口上,创建 Server 后我们看到有一个回调函数,

在调用上面函数的时候传入一个参数,这个参数也是函数,并且接受了 socket ,这个由其他方法构造的一个管道(pipe),他的作用就是用来数据交互的。

pipe 是需要 Client 跟 Server 打招呼才能建立的,如果此刻没有客户端访问 Server,这个 socket 就不会存在了。

客户端------net.connect 顾名思义,就是连接到服务端,第一个参数是对象,设置端口(port)为 8124,也就是我们服务器监听的端口,由于没有设置 host 参数,那默认就是 localhost (本地)。

在 Server 中,socket 是管道的一端,而在 client 中,client 本身就是管道的一端,如果是多个客户端连接 Server,Server 会新建多个 socket,每个 socket 对应一个 client。

运行结果:

三,案例引入

(1),下面代码仅仅是服务器向客户端输出一段文本,完成服务端到客户端的单向通讯。

 1 //  Sever --> Client 的单向通讯
 2 var net = require('net');
 3
 4 var chatServer = net.createServer();
 5
 6 chatServer.on('connection', function(client) {
 7   client.write('Hi!\n'); // 服务端向客户端输出信息,使用 write() 方法
 8   client.write('Bye!\n');
 9
10   client.end(); // 服务端结束该次会话
11 });
12
13 chatServer.listen(9000);

Telnet测试一下:telnet 127.0.0.1:9000 

执行 telnet 后,与服务点连接,反馈 Hi! Bye! 的字符,并立刻结束服务端程序终止连接。

如果我们要服务端接到到客户端的信息?

可以监听 server.data 事件并且不要中止连接(否则会立刻结束无法接受来自客户端的消息)。

(2),监听 server.data 事件并且不要中止连接(否则会立刻结束无法接受来自客户端的消息)。

 1 // 在前者的基础上,实现 Client --> Sever 的通讯,如此一来便是双向通讯
 2 var net = require('net');
 3 var chatServer = net.createServer(),
 4     clientList = [];
 5
 6 chatServer.on('connection', function(client) {
 7   // JS 可以为对象自由添加属性。这里我们添加一个 name 的自定义属性,用于表示哪个客户端(客户端的地址+端口为依据)
 8   client.name = client.remoteAddress + ':' + client.remotePort;
 9   client.write('Hi ' + client.name + '!\n');
10   clientList.push(client);
11   client.on('data', function(data) {
12      broadcast(data, client);// 接受来自客户端的信息
13   });
14 });
15 function broadcast(message, client) {
16     for(var i=0;i<clientList.length;i+=1) {
17       if(client !== clientList[i]) {
18         clientList[i].write(client.name + " says " + message);
19       }
20     }
21 }
22 chatServer.listen(9000);

上面是不是一个完整功能的代码呢?我们说还有一个问题没有考虑进去:那就是一旦某个客户端退出,却仍保留在 clientList 里面,这明显是一个空指针。

(3),处理clientList

 1 chatServer.on('connection', function(client) {
 2   client.name = client.remoteAddress + ':' + client.remotePort
 3   client.write('Hi ' + client.name + '!\n');
 4
 5   clientList.push(client)
 6
 7   client.on('data', function(data) {
 8     broadcast(data, client)
 9   })
10
11   client.on('end', function() {
12     clientList.splice(clientList.indexOf(client), 1); // 删除数组中的制定元素。
13   })
14 })

Node TCP API 已经为我们提供了 end 事件,即客户端中止与服务端连接的时候发生。

(4),优化broadcast

 1 function broadcast(message, client) {
 2   var cleanup = []
 3   for(var i=0;i<clientList.length;i+=1) {
 4     if(client !== clientList[i]) {
 5
 6       if(clientList[i].writable) { // 先检查 sockets 是否可写
 7         clientList[i].write(client.name + " says " + message)
 8       } else {
 9         cleanup.push(clientList[i]) // 如果不可写,收集起来销毁。销毁之前要 Socket.destroy() 用 API 的方法销毁。
10         clientList[i].destroy()
11       }
12
13     }
14   }  //Remove dead Nodes out of write loop to avoid trashing loop index
15   for(i=0;i<cleanup.length;i+=1) {
16     clientList.splice(clientList.indexOf(cleanup[i]), 1)
17   }
18 }

注意的是一旦 “end” 没有被触发,会出现异常,所以才做优化工作。

(5),Net API 中还提供一个 error 事件,用于捕捉客户端的异常

client.on('error', function(e) {console.log(e);
});

四,总结一下

1,理解开篇的相关概念

2,认识Http与Net模块之间的关系

3,结合本文的例子,查阅相关api去实践

4,socket客户端与服务器端之间的通信思想

5,有兴趣可以完善一下那个聊天室的例子

        哈哈哈,本篇结束,未完待续,希望和大家多多交流够沟通,共同进步。。。。。。呼呼呼……(*^__^*)            

转载于:https://www.cnblogs.com/bigbearbb/p/4205627.html

大熊君大话NodeJS之------Net模块相关推荐

  1. nodejs linux模块全局,nodejs笔记一--模块,全局process对象;

    一.os模块可提供操作系统的一些基本信息,它的一些常用方法如下: var os = require("os"); var result = os.platform(); //查看操 ...

  2. nodejs没有net模块_Node.js实战16:用http模块创建web服务器

    Nodejs的http模块,是基于net.server,经过c++二次封装,也是nodejs的核心模块. 功能比net.server更强,可解析和操作更多细节内容,如值.content-length. ...

  3. Nodejs的http模块

    一.http服务器 我们知道传统的HTTP服务器是由Aphche.Nginx.IIS之类的软件来搭建的,但是Nodejs并不需要,Nodejs提供了http模块,自身就可以用来构建服务器.例如,下面的 ...

  4. 大熊君学习html5系列之------History API(SPA单页应用的必备------重构完结版)

    一,开篇分析 Hi,大家好!大熊君又和大家见面了,(*^__^*) 嘻嘻--,这系列文章主要是学习Html5相关的知识点,以学习API知识点为入口,由浅入深的引入实例, 让大家一步一步的体会" ...

  5. Nodejs中的模块系统

    一.模块化的定义 ①具有文件作用域 ②具有通信规则:加载和导出规则 二.CommonJS模块规范 1.nodejs中的模块系统,具有文件作用域,也具有通信规则,使用require方法加载模块,使用ex ...

  6. nodejs的mysql模块_Nodejs的mysql模块学习(一)

    介绍 mysql npm包 是一个nodejs的模块,由JavaScript编写 安装 npm install mysql 建立连接 var mysql = require('mysql');//引用 ...

  7. Nodejs全局安装模块后找不到命令的解决方法

    Nodejs全局安装模块后找不到命令的解决方法 参考文章: (1)Nodejs全局安装模块后找不到命令的解决方法 (2)https://www.cnblogs.com/xiaoyucoding/p/1 ...

  8. Nodejs的url模块方法

    Nodejs的url模块方法 nodejs里面的一个简单的模块,url模块.这个url的模块要使用的话需要先引入.若只是在命令行里比如cmd或git bash 等使用url这个模块的话,是不需要req ...

  9. nodejs中的模块的理解

    nodejs所谓的模块就是一个文件,或者是匿名函数.(CommonJs) require exports module.exports. 为什么直接console.log(typeof require ...

最新文章

  1. Java语言中的生僻知识
  2. Asp.net中的常用路径
  3. hihocoder #1388 : Periodic Signal NTTFFT
  4. mybatis之动态SQL操作之查询
  5. UOJ#218. 【UNR #1】火车管理 线段树 主席树
  6. 【Calcite】Calcite 的SQL解析
  7. 美国AI出口限令倒计时,硅谷直喊“下手轻点”,担心推动中国技术发展
  8. 2432功率计使用说明_Quarq功率计的安装、使用和维护
  9. Python_Python处理JSON文件
  10. 解决办法:VirtualBox只能安装32位的问题
  11. 从0开始写sql脚本到执行sql脚本。
  12. 在线解析短视频去水印工具
  13. linux telnet trying,telnet ip port 显示trying一般是什么情况?急。。。
  14. HTML2——图像、超链接
  15. 利用js制作动态小时钟
  16. 英汉对照名言隽语(四)
  17. Java小游戏-俄罗斯方块
  18. C++条件运算符(三目运算符+逗号运算符)案例实练
  19. opengles图像处理之图片锐化处理
  20. 解决蓝牙鼠标和电脑连接出现卡顿的情况

热门文章

  1. c#里有遍历目录及子目录以树的形式展现
  2. Flutter 开发应用第一个页面
  3. Android--使用LayoutInflater加载布局文件的三种方法
  4. [转]Linux之ACL权限
  5. SQLServer 行转列,统计,二次分组
  6. Javascript事件机制兼容性解决方案
  7. 【Vue】实例对象的生命周期(方法详解)
  8. JavaScript学习笔记之BOM篇,认识几种常见的浏览器对象
  9. Linux驱动(14)--字符类设备与驱动
  10. PCL综述—三维图像处理