源码网商城,靠谱的源码在线交易网站 我的订单 购物车 帮助

源码网商城

Nodejs学习笔记之NET模块

  • 时间:2020-11-17 10:04 编辑: 来源: 阅读:
  • 扫一扫,手机访问
摘要:Nodejs学习笔记之NET模块
[b]一,开篇分析[/b] 从今天开始,我们来深入具体的模块学习,这篇文章是这个系列文章的第三篇,前两篇主要是以理论为主,相信大家在前两篇的学习中, 对NodeJS也有一个基本的认识,没事!!!趁热打铁,让我们继续将NodeJS进行到底,好了废话不多说,直接进入今天的主题 “Net模块” ,那么”Net“应该如何理解那? 它是做什么用的那?([code]Net[/code]模块可用于创建Socket服务器或Socket客户端。NodeJS 的数据通信,最基础的两个模块是 Net 和 Http,前者是基于 Tcp 的封装,后者本质还是 Tcp 层,只不过做了比较多的数据封装,我们视为表现层)。 这里参考一下NodeJS “http.js” 中的源码: [img]http://files.jb51.net/file_images/article/201501/2015011310091917.png[/img] 从图中不难看出 HttpServer继承了Net类,具有了相关的通信能力,做了比较多的数据封装,我们视为更高级的表现层。 扩展知识(以下是“inherits”的源码):
[u]复制代码[/u] 代码如下:
exports.inherits = function(ctor, superCtor) {   ctor.super_ = superCtor;   ctor.prototype = Object.create(superCtor.prototype, {     constructor: {       value: ctor,       enumerable: false,       writable: true,       configurable: true     }   }); };
功能是实现继承复用。 刚才做了一个简要的概述,里面有一些常用的概念,这里做个简短的概念普及介绍:   (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编程的接口。 [b]二,体验一把[/b] 好了,概念我们也有了,来个例子: 1,建立server.js
[u]复制代码[/u] 代码如下:
var net = require('net') ; var server = net.createServer(function(c) { // Connection监听器   console.log("服务器已连接") ;   c.on("end", function() {     console.log("服务器已断开") ;   }) ;   c.write("Hello,Bigbear !\r\n") ;   c.pipe(c) ; }) ; server.listen(8124, function() { // Listening监听器   console.log("服务器已绑定") ; }) ;
2,建立client.js
[u]复制代码[/u] 代码如下:
var net = require('net') ; var client = net.connect({     port: 8124 },function(){ // connect监听器   console.log("客户端已连接") ;   client.write('Hello,Baby !\r\n') ; }); client.on("data", function(data) {   console.log(data.toString()) ;   client.end() ; }); client.on("end", function(){   console.log("客户端断开连接") ; }) ;
分析一下: 服务端------[code]net.createServer[/code]创建一个 TCP 服务,这个服务绑定(server.listen)在 8124 这个端口上,创建 Server 后我们看到有一个回调函数, 在调用上面函数的时候传入一个参数,这个参数也是函数,并且接受了 socket ,这个由其他方法构造的一个管道(pipe),他的作用就是用来数据交互的。 pipe 是需要 Client 跟 Server 打招呼才能建立的,如果此刻没有客户端访问 Server,这个 socket 就不会存在了。 [code]客户端------net.connect[/code]顾名思义,就是连接到服务端,第一个参数是对象,设置端口(port)为 8124,也就是我们服务器监听的端口,由于没有设置 host 参数,那默认就是 localhost (本地)。 在 Server 中,socket 是管道的一端,而在 client 中,client 本身就是管道的一端,如果是多个客户端连接 Server,Server 会新建多个 socket,每个 socket 对应一个 client。 运行结果: [img]http://files.jb51.net/file_images/article/201501/2015011310091918.jpg[/img] [b]三,案例引入[/b] (1),下面代码仅仅是服务器向客户端输出一段文本,完成服务端到客户端的单向通讯。
[u]复制代码[/u] 代码如下:
//  Sever --> Client 的单向通讯 var net = require('net'); var chatServer = net.createServer(); chatServer.on('connection', function(client) {   client.write('Hi!\n'); // 服务端向客户端输出信息,使用 write() 方法   client.write('Bye!\n');   client.end(); // 服务端结束该次会话 }); chatServer.listen(9000);
Telnet测试一下:telnet127.0.0.1:9000 执行 telnet后,与服务点连接,反馈 Hi! Bye! 的字符,并立刻结束服务端程序终止连接。 如果我们要服务端接到到客户端的信息? 可以监听 server.data 事件并且不要中止连接(否则会立刻结束无法接受来自客户端的消息)。 (2),监听 server.data 事件并且不要中止连接(否则会立刻结束无法接受来自客户端的消息)。
[u]复制代码[/u] 代码如下:
// 在前者的基础上,实现 Client --> Sever 的通讯,如此一来便是双向通讯 var net = require('net'); var chatServer = net.createServer(),        clientList = []; chatServer.on('connection', function(client) {   // JS 可以为对象自由添加属性。这里我们添加一个 name 的自定义属性,用于表示哪个客户端(客户端的地址+端口为依据)   client.name = client.remoteAddress + ':' + client.remotePort;    client.write('Hi ' + client.name + '!\n');    clientList.push(client);    client.on('data', function(data) {         broadcast(data, client);// 接受来自客户端的信息    }); }); function broadcast(message, client) {      for(var i=0;i<clientList.length;i+=1) {          if(client !== clientList[i]) {              clientList[i].write(client.name + " says " + message);          }      } } chatServer.listen(9000);
上面是不是一个完整功能的代码呢?我们说还有一个问题没有考虑进去:那就是一旦某个客户端退出,却仍保留在 clientList里面,这明显是一个空指针。 (3),处理clientList
[u]复制代码[/u] 代码如下:
chatServer.on('connection', function(client) {   client.name = client.remoteAddress + ':' + client.remotePort   client.write('Hi ' + client.name + '!\n');   clientList.push(client)   client.on('data', function(data) {     broadcast(data, client)   })   client.on('end', function() {     clientList.splice(clientList.indexOf(client), 1); // 删除数组中的制定元素。   }) })
NodeTCPAPI已经为我们提供了 end 事件,即客户端中止与服务端连接的时候发生。 (4),优化broadcast
[u]复制代码[/u] 代码如下:
function broadcast(message, client) {   var cleanup = []   for(var i=0;i<clientList.length;i+=1) {     if(client !== clientList[i]) {       if(clientList[i].writable) { // 先检查 sockets 是否可写         clientList[i].write(client.name + " says " + message)       } else {         cleanup.push(clientList[i]) // 如果不可写,收集起来销毁。销毁之前要 Socket.destroy() 用 API 的方法销毁。         clientList[i].destroy()       }     }   }  //Remove dead Nodes out of write loop to avoid trashing loop index   for(i=0;i<cleanup.length;i+=1) {     clientList.splice(clientList.indexOf(cleanup[i]), 1)   } }
注意的是一旦 “end” 没有被触发,会出现异常,所以才做优化工作。 (5),NetAPI中还提供一个 error 事件,用于捕捉客户端的异常
[u]复制代码[/u] 代码如下:
client.on('error', function(e) {   console.log(e); });
[b]四,总结一下[/b] 1,理解开篇的相关概念 2,认识Http与Net模块之间的关系 3,结合本文的例子,查阅相关api去实践 4,socket客户端与服务器端之间的通信思想 5,有兴趣可以完善一下那个聊天室的例子
  • 全部评论(0)
联系客服
客服电话:
400-000-3129
微信版

扫一扫进微信版
返回顶部