Dnode介绍
Dnode是一个提供异步双向远程方法调用的类库。网络socket和websocket风格的socket.io通信已经成为可能,所以系统的进程之间可以相互通信并且可以与运行在浏览器端的用户进程使用相同的接口。
远程方法调用(RMI)是面向对象中远程过程调用的表兄弟。在RMI中,连接的每一端都持有另一端能够调用其方法的一个远程对象。
Dnode所有的远程方法调用都是异步的。不同于明确返回结果的做法,宿主的(远端)方法通过执行回调方法来“传递”返回值到另一个连接端(本地),而该回调是被作为一个参数传递过来的。这些回调在那些定义它们的一端(通常为客户端)被执行,并且它们的一个代理被传递到远程,所以这里没有eval()
下面是一个简单的例子:
-
- var DNode = require('dnode');
-
- var server = DNode({
- timesTen : function (n,f) { f(n * 10) },
- }).listen(6060);
-
- var DNode = require('dnode');
- var sys = require('sys');
-
- DNode.connect(6060, function (remote) {
- remote.timesTen(5, function (result) {
- sys.puts(result);
- });
- });
接着,开启两个Cygwin客户端,分别编译并执行Server端代码和Client端代码:
Server:
Client:
不像许多异步RPC系统,Dnode允许程序员将函数作为参数传递给远程方法。回调会被自动地刷新并且从参数列表中递归被收集。所以它们可以被任意嵌套。
另外,连接的每一边都可以调用另一边的方法以及另一边提供的回调方法,这些回调方法可以为其自身也可以为任何可以被序列化为JSON参数的方法。
双向范例
这里有一个关于客户端调用服务端的一个方法,而服务端又调用客户端的一个方法的例子:
-
- var DNode = require('dnode');
-
- DNode(function(client){
- this.timesX=function(n,f){
- client.x(function(x){
- f(n*x);
- });
- }
- }).listen(6060);
-
- var DNode = require('dnode');
- var sys = require('sys');
-
- DNode({
- x:function(f){ f(20) }
- }).connect(6060,function(remote){
- remote.timesX(3,function(res){
- sys.puts(res);
- }
- });
-
- });
执行方法同上,效果如下:
DNode浏览器示例
在浏览器与node.js Dnode服务器之间的websocket形式的连接的可行性需要感谢socket.io。接下来的示例应该运行在Chrome、Firefox、Opera以及IE 5.5+以上的版本。
本示例来自node_modules\dnode\examples\web-http下:
server.js
- var http = require('http');
- var fs = require('fs');
- var dnode = require('dnode');
-
- var index = fs.readFileSync(__dirname + '/index.html');
-
- var server = http.createServer(function (req, res) {
- if (req.url === '/') {
- res.writeHead(200, { 'Content-Type' : 'text/html' });
- res.end(index);
- }
- });
-
- dnode(function (client) {
- this.cat = function (cb) {
- cb('meow');
- };
- }).listen(server);
-
- server.listen(6857);
- console.log('http://localhost:6857/');
注解:__dirname表示当前文件所在文件夹,fs.readFileSync方法为同步读取文件,返回值是二进制流。
index.html
- <html>
- <head>
- <script src="/dnode.js" type="text/javascript"></script>
- <script type="text/javascript">
- window.onload = function () {
- DNode.connect(function (remote) {
- remote.cat(function (says) {
- document.getElementById('says').innerHTML = says;
- });
- });
- };
- </script>
- </head>
- <body>
- The cat says <span id="says">?</span>.
- </body>
- </html>
编译:
注:必须定位到文件所在的目录才可以使用node命令后面跟相对路径下的文件名编译JS。
在浏览器地址栏敲入:http://localhost:6857/,便可得到如下输出:
解析:因为http服务端正在监听来自6857端口,当发现有请求,并且发现后面跟有“/”,则输出index.html到客户端。由于服务端的DNode侦听6857端口,而客户端页面加载完成,就开始连接服务端的DNode,并执行回调。来自服务端的代理(remote),执行定义在服务端的方法cat(),方法cat需要一个函数(客户端定义)作为参数。
最终ID为says的span标签的文本就变为meow。
安装
Dnode可以通过npm获得,npm是一个node.js库的包管理器。你可以通过下面的命令安装(在cygwin中执行下面的命令):
Dnode依赖于如下的Module:Socket.IO-node, bufferlist 、traverse。所有的这些都可以通过npm获得,并且当你在执行完上面的命令之后,它们已经自动安装了。
当然还有一些有趣的范例都在dnode的example,有兴趣的童鞋可以自己研究一下~