这里有新鲜出炉的 Node.JS 入门教程,程序狗速度看过来!
Node.js 是一个基于 Chrome JavaScript 运行时建立的一个平台, 用来方便地搭建快速的 易于扩展的网络应用 · Node.js 借助事件驱动, 非阻塞 I/O 模型变得轻量和高效, 非常适合 运行在分布式设备 的 数据密集型 的实时应用
这篇文章主要为大家详细介绍了 Node.js 实现数据推送的相关资料,感兴趣的小伙伴们可以参考一下
场景:后端更新数据推送到客户端(Java 部分使用 Tomcat 服务器)。
后端推送数据的解决方案有很多,比如轮询、Comet、webSocket。
1. 轮询对于后端来说开发成本最低,就是按照传统的方式处理 Ajax 请求并返回数据,在学校的时候实验室的项目一直都采用轮询,因为它最保险也最容易实现。但轮询带来的通信资源的浪费是无法忽视的,无论数据是否改变,都照常发送请求并响应,而且每次 HTTP 请求都带有很长的头部信息。
2. Comet 的概念是长连接,客户端发送请求后,后端将连接保持下来,直到连接超时或后端返回数据时再重新建立连接,有效的将通信资源转移到了服务器上,实际消耗的是服务器资源。
3. WebSocket 是 html5 提供的一种全双工通信技术,通过 "握手" 实现客户端与服务器之间的通信,实时性好,携带的头部也较小,目前支持的浏览器如下:
理想的情况是采取 WebSocket 与 Comet 结合的方式,对 IE8 等浏览器采取 Comet 方式,做降级处理。但是这样一来,后端需要实现两种处理请求的逻辑,即 WebSocket 与 Comet。所以,本文加入 Node.js,之所以这样做,是将处理 WebSocket(或 Comet)的逻辑转移到 Node.js 部分,不给后端 "添麻烦",因为在实际情况下,前端开发人员推动后端开发人员并不容易。Node.js 作为浏览器与 Java 业务逻辑层通信的中间层,连接客户端与 Tomcat,通过 Socket 与 Tomcat 进行通信(是 Socket,不是 WebSocket,后端需要实现 Socket 接口。
在客户端,WebSocket 与 Comet 通过 Socket.io 实现,Socket.io 会针对不同的浏览器版本或者不同客户端选择合适的实现方式(WebSocket, long pull..),Socket.io 的引入让处理 WebSocket(或长连接)变的很容易。Socket.io
客户端引入 socket.io:
客户端 JavaScript 代码:
- var socket = io.connect('127.0.0.1:8181');
- // 发送数据至服务器
- socket.emit('fromWebClient', jsonData);
- // 从服务器接收数据
- socket.on('pushToWebClient', function (data) {
- // do sth.
- });
Node.js 服务器代码:
- var http = require('http'),
- app = http.createServer().listen('8181'),
- io = require('socket.io').listen(app);
- io.sockets.on('connection',
- function(socketIO) {
- // 从客户端接收数据
- socketIO.on('fromWebClient',
- function(webClientData) {
- // do sth.
- });
- // 客户端断开连接
- socketIO.on('disconnect',
- function() {
- console.log('DISCONNECTED FROM CLIENT');
- });
- // 向客户端发送数据
- socketIO.emit('pushToWebClient', jsonData);
- });
建立好客户端同 Node.js 服务器的连接只是第一步,下面还需要建立 Node.js 服务器与 Java 业务逻辑层的联系。这时,Node.js 服务器则作为客户端,向 Tomcat 发送 TCP 连接请求。连接成功后,Node.js 服务器和 Tomcat 建立了一条全双工的通道,而且是唯一的一条,不论有多少个客户端请求,都从 Node.js 服务器转发至 Tomcat;同样,Tomcat 推送过来的数据,也经由 Node.js 服务器分发至各个客户端。
这里存在一个问题,就是在 WebSocket 连接与 Socket 连接都建立好之后,两次连接彼此之间是屏蔽的。Tomcat 不知道是哪次 WebSocket 连接发送过来的数据,也不知道是哪个客户端发来的数据。当然,Node.js 可以利用 session id 发送至 Tomcat 来标识是哪一个客户端,但本文采用的是另外一种办法。
客户端同 Node.js 建立 WebSocket 连接时,每个连接都会包含一个实例,这里称它为 socketIO。每个 socketIO 都有一个 id 属性用来唯一标识这个连接,这里称它为 socket_id。利用 socket_id,在 Node.js 服务器建立一个映射表,存储每一个 socketIO 与 socket_id 的映射关系。Node.js 服务器发送数据给 Tomcat 时带上这个 socket_id,再由 Java 部分进行一系列处理以后封装好每个客户端需要的不同数据一并返回,返回的数据里要有与 socket_id 的对应关系。这样,Node.js 服务器收到 Tomcat 发来的数据时,通过前面提到的映射表由不同的 socketIO 分发至不同的客户端。
Node.js 服务器代码:
- var http = require('http'),
- net = require('net'),
- app = http.createServer().listen('8181'),
- io = require('socket.io').listen(app),
- nodeServer = new net.Socket();
- // 连接到Tomcat
- nodeServer.connect(8007, '127.0.0.1',
- function() {
- console.log('CONNECTED');
- });
- // 存储客户端的WebSocket连接实例
- var aSocket = {};
- // 同客户端建立连接
- io.sockets.on('connection',
- function(socketIO) {
- // 从客户端接收数据,然后发送至Tomcat
- socketIO.on('fromWebClient',
- function(webClientData) {
- // 存储至映射表
- aSocket[socketIO.id] = socketIO;
- // 发送至Tomcat的数据中添加socket_id
- webClientData['sid'] = socketIO.id;
- // 发送String类型的数据至Tomcat
- nodeServer.write(JSON.stringify(webClientData));
- });
- // 客户端断开连接
- socketIO.on('disconnect',
- function() {
- console.log('DISCONNECTED FROM CLIENT');
- });
- });
- // 从Tomcat接收数据
- nodeServer.on('data',
- function(data) {
- var jsonData = JSON.parse(data.toString());
- // 分发数据至客户端
- for (var i in jsonData.list) {
- aSocket[jsonData.list[i]['sid']].emit('pushToWebClient', jsonData.list[i].data);
- }
- });
上面的代码省略了一些逻辑,比如 Node.js 服务器从 Tomcat 接收的数据分为两种,一种是推送过来的数据,另外一种是响应请求的数据,这里统一处理推送过来的数据。
在处理通信时,Node.js 发送至 Tomcat 的数据是 String 格式,而从 Tomcat 接收的数据为 Buffer 对象(8 进制),需要转化为 String 之后再转化为 json 发送至客户端。
本文只是给出一个这样两次连接的简单例子,具体的业务中需要加入许多东西。既然在项目中引入了 Node.js,就需要前端承担更多的事情,比如对数据的处理、缓存、甚至加入很多业务逻辑。
来源: http://www.phperz.com/article/17/0403/266323.html