设为首页 收藏本站
查看: 1603|回复: 0

[经验分享] 大熊君大话NodeJS之------Net模块

[复制链接]

尚未签到

发表于 2017-2-22 10:33:51 | 显示全部楼层 |阅读模式
  一,开篇分析
  从今天开始,我们来深入具体的模块学习,这篇文章是这个系列(大熊君大话NodeJS)文章的第三篇,前两篇主要是以理论为主,相信大家在前两篇的学习中,
  对NodeJS也有一个基本的认识,没事!!!趁热打铁,让我们继续将NodeJS进行到底,好了废话不多说,直接进入今天的主题 “Net模块” ,那么”Net“应该如何理解那?
  它是做什么用的那?(Net模块可用于创建Socket服务器或Socket客户端。 NodeJS 的数据通信,最基础的两个模块是 Net 和 Http,前者是基于 Tcp 的封装,后者本质还是 Tcp 层,只不过做了比较多的数据封装,我们视为表现层)。

  这里参考一下NodeJS “http.js” 中的源码:
   DSC0000.png
  从图中不难看出 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。
  运行结果:
DSC0001.jpg

  三,案例引入
  (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) {      
18         clientList.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) {
5
6       if(clientList.writable) { // 先检查 sockets 是否可写
7         clientList.write(client.name + " says " + message)
8       } else {
9         cleanup.push(clientList) // 如果不可写,收集起来销毁。销毁之前要 Socket.destroy() 用 API 的方法销毁。
10         clientList.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), 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,有兴趣可以完善一下那个聊天室的例子
   哈哈哈,本篇结束,未完待续,希望和大家多多交流够沟通,共同进步。。。。。。呼呼呼……(*^__^*)            

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-345597-1-1.html 上篇帖子: 大熊君大话NodeJS之开篇------Why NodeJS(将Javascript进行到底) 下篇帖子: nodejs实现简易MVC
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表