Nodejs学习笔记之NET模块

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Nodejs学习笔记之NET模块相关的知识,希望对你有一定的参考价值。

参考技术A

一,开篇分析
从今天开始,我们来深入具体的模块学习,这篇文章是这个系列文章的第三篇,前两篇主要是以理论为主,相信大家在前两篇的学习中,
对NodeJS也有一个基本的认识,没事!!!趁热打铁,让我们继续将NodeJS进行到底,好了废话不多说,直接进入今天的主题
“Net模块”
,那么”Net“应该如何理解那?
它是做什么用的那?(Net模块可用于创建Socket服务器或Socket客户端。NodeJS
的数据通信,最基础的两个模块是
Net

Http,前者是基于
Tcp
的封装,后者本质还是
Tcp
层,只不过做了比较多的数据封装,我们视为表现层)。
这里参考一下NodeJS
“http.js”
中的源码:
从图中不难看出
HttpServer继承了Net类,具有了相关的通信能力,做了比较多的数据封装,我们视为更高级的表现层。
扩展知识(以下是“inherits”的源码):
复制代码
代码如下:
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编程的接口。
二,体验一把
好了,概念我们也有了,来个例子:
1,建立server.js
复制代码
代码如下:
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
复制代码
代码如下:
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("客户端断开连接")
;
)
;
分析一下:
服务端------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),下面代码仅仅是服务器向客户端输出一段文本,完成服务端到客户端的单向通讯。
复制代码
代码如下:
// 
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
事件并且不要中止连接(否则会立刻结束无法接受来自客户端的消息)。
复制代码
代码如下:
//
在前者的基础上,实现
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
复制代码
代码如下:
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
复制代码
代码如下:
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
事件,用于捕捉客户端的异常
复制代码
代码如下:
client.on(\'error\',
function(e)

 
console.log(e);
);
四,总结一下
1,理解开篇的相关概念
2,认识Http与Net模块之间的关系
3,结合本文的例子,查阅相关api去实践
4,socket客户端与服务器端之间的通信思想
5,有兴趣可以完善一下那个聊天室的例子

NodeJS学习笔记之MongoDB模块

其中还有,nodejs远程连接mysql数据库

一,开篇分析

这篇属于扩展知识篇,因为在下面的文章中会用到数据库操作,所以今天就来说说它(Mongodb模块)。

(1),简介

 MongoDB是一个基于分布式文件存储的数据库。由C++语言编写。旨在为WEB应用提供可扩展的高性能数据存储解决方案。

 MongoDB是一个高性能,开源,无模式的文档型数据库,是当前NoSql数据库中比较热门的一种。

 MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。他支持的数据结构非常松散,是类似json的bjson格式,因此可以存储比较复杂的数据类型。Mongo最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。

传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成,MongoDB是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。

MongoDB对于关系型数据库里的表,但是集合中没有列、行和关系概念,这体现了模式自由的特点。

(2),特点

 它的特点是高性能、易部署、易使用,存储数据非常方便。主要功能特性有:

 1)面向集合存储,易存储对象类型的数据。
 2)模式自由。
 3)支持动态查询。
 4)支持完全索引,包含内部对象。
 5)支持查询。
 6)支持复制和故障恢复。
 7)使用高效的二进制数据存储,包括大型对象(如视频等)。
 8)自动处理碎片,以支持云计算层次的扩展性。
 9)支持RUBY,PYTHON,JAVA,C++,PHP,C#等多种语言。
 10)文件存储格式为BSON(一种JSON的扩展)。
 11)可通过网络访问。

一、根据之前的文章启动mongo数据库时,(一定要先启动mongo数据库)

在shell 命令窗口键入如下命令:" use bb" (use 命令用来切换当前数据库,如果该数据库不存在,则会先新建一个)。

在shell 命令窗口键入如下命令:“ db.users.insert({"name":"bigbear","password":"12345678"})”,(这条命令是向users 集合中插入一条数据,如果集合users不存在,则会先新建一个,然后再插入数据,参数以JSON格式传入)。在shell 命令窗口键入如下命令:“db.users.find()” (显示users集合下的所有数据文档),如下图:

注意图中的“_id”,系统给每条记录自动分配了一个惟一主键 _id 。

好了!基本的功能够用了,后面如果需要额外的操作逐步补充,由于篇幅有限主要说的是NodeJS操作Mongodb,所以暂时告一段落。

 

二、然后进入用nodejs操作该数据库的部分

 var mongodb = require("mongodb") ;
 var server = new mongodb.Server("localhost",27017,{
     auto_reconnect : true
 }) ;
 var conn = new mongodb.Db("wly",server,{
     safe : true
 }) ;
 conn.open(function(error,db){
     if(error) throw error ;
     db.collection("users",{
         safe : true
     },function(err,collection){
         if(err) throw err ;
         collection.find().toArray(function(e,docs){
             if(e) throw e ;
             console.log(docs) ;
         }) ; 
     }) ;
 }) ;

结果如下图:

本文操作的app.js下载链接在此

 

以上是关于Nodejs学习笔记之NET模块的主要内容,如果未能解决你的问题,请参考以下文章

NodeJS学习笔记之MongoDB模块

NodeJS学习笔记之Node中的数据交互

系列文章--Node.js学习笔记系列

Nodejs学习笔记-----EventEmitter

Nodejs学习笔记----- 模块系统和函数

NodeJS学习笔记之Http模块