您的位置:首页 > 编程语言 > Java开发

Erlang与JAVA的交互操作

2008-09-19 12:51 239 查看
http://www.lupaworld.com/action-viewstutorial-itemid-10193.html

Erlang与JAVA的交互操作

来源: LUPA开源社区文章来源于http://www.lupaworld.com

试了一下传说中的 JInterface ,使用 OtpErlang.jar 的整个过程其实非常简单,似乎比 JMS 的程序都简单。

首先,我们要用 java 实现的原始 erlang 程序如下,没错,就是巨简单的 echo ,我们的目标是要把它用 java 来改写,不仅写服务端,也要写客户端。

下载: echo_client.erl

-module(echo_client).

 

-export([run/0]).

 

run() ->

    Msg = "Hello Echo!",

    {echo, abc@merlin} ! {self(), Msg},

    io:format("send ~p ~n", [Msg]),

    receive

        Res ->

            io:format("received ~p ~n", [Res])

    end.

下载: echo_server.erl

-module(echo_server).

 

-export([start/0]).

 

start() ->

    register(echo, self()),

    io:format("echo start~n", []),

    loop().

 

loop() ->

    receive

        {Pid, Msg} ->

            io:format("received ~p from ~p~n", [Msg, Pid]),

            Pid ! Msg;

        Any ->

            io:format("received ~p ~n", [Any])

    end,

    loop().

写得并不严密,用了一堆硬编码,主要是个示例,就那么个意思,大家将就着看。

先说一下 JInterface 的一些基本概念。JInterface 的目的是:为 Java 提供一个包,使得 Java
程序在外部可以看起来就像一个标准的 Erlang Node 能以标准的 Erlang 方式与其他的节点进行通讯。它包装了 Erlang
节点之间分布式的通讯协议,编码解码,以及基本的 Erlang 操作,也就是 pid register send receive link
unlink 等等,朴实无华。不过,作为两个语言之间的接口包,有了这些基本功能也就足够了。

根据 Erlang 的目录惯例, JInterface 的 Jar 在
ERLANG_HOME/lib/jinterface-x.x/priv 目录下,名字为 OtpErlang.jar 。注意,必须使用和你当前
Erlang 版本下的包,否则出了什么妖怪问题,别来问我,就算是问我,我也不知道该怎么办。:D 之前一直有一个误解,想当然的以为
JInterface 会用 JNI 什么的来实现,而自从碰过一次以后,对 JNI
这种“难以掌控”的东西总觉得有点畏难,所以,迟迟都没有动手,没想到,竟是纯 Java 实现的一个包。用起来方便,部署起来也漂亮。爽!

闲话休提,直接上代码得了。先是 Client 的代码。

下载: ErlangEchoClient.java

package com.test.erlang;

 

import java.io.IOException;

 

import com.ericsson.otp.erlang.*;

 

public class ErlangEchoClient {

   

    public static void main(String[] args) throws IOException {

       

        String v = System.getProperties().getProperty("OtpConnection.trace");

        System.out.println("OtpConnection.trace="+v);

       

        OtpNode self = new OtpNode("bcd", "123");

       

        System.out.println("node:"+self.node());

        System.out.println("cookie:"+self.cookie());

       

        if (self.ping("abc", 2000)) {

            System.out.println("remote is up");

        } else {

            System.out.println("remote is not up");

            return;

        }

       

        String text = "Hi there";

       

        OtpMbox mbox = self.createMbox();

       

        OtpErlangObject[] msg = new OtpErlangObject[2];

        msg[0] = mbox.self();

        msg[1] = new OtpErlangString(text);

        OtpErlangTuple tuple = new OtpErlangTuple(msg);

 

        mbox.send("echo", "abc", tuple);

       

        System.out.println("send:"+text);

 

        try {

           

            OtpErlangObject reply = mbox.receive();

           

            System.out.println("receive[raw]:"+reply);

           

            if (reply instanceof OtpErlangString) {

                OtpErlangString text2 = (OtpErlangString) reply;

               

                System.out.println("receive[text]:"+text2);

 

            }

        } catch (Exception e) {

            System.out.println("" + e);

        }

    }

 

}

下载: ErlangEchoServer.java

package com.test.erlang;

 

import java.io.IOException;

 

import com.ericsson.otp.erlang.*;

 

public class ErlangEchoServer {

   

    public static void main(String[] args) throws IOException {

       

        String v = System.getProperties().getProperty("OtpConnection.trace");

        System.out.println("OtpConnection.trace="+v);

       

        OtpNode self = new OtpNode("server1", "123");

       

        System.out.println("node:"+self.node());

        System.out.println("cookie:"+self.cookie());

       

        OtpMbox mbox = self.createMbox("echo");

       

        String[] names = self.getNames();

        for(int i=0; i<names.length; i++) System.out.println("name:"+names[i]);

       

        while (true) {

            try {

                OtpErlangObject request = mbox.receive();

               

                System.out.println("receive[raw]:"+request);

               

                if (request instanceof OtpErlangTuple) {

                    OtpErlangTuple t = (OtpErlangTuple) request;

                    OtpErlangPid pid = (OtpErlangPid) (t.elementAt(0));

                    OtpErlangString text = (OtpErlangString) (t.elementAt(1));

                   

                    System.out.println("receive[text]:"+text);

                   

                    OtpErlangString response = text;

                   

                    mbox.send(pid, response);

                }

            } catch (Exception e) {

                System.out.println("" + e);

            }

        }

    }

 

}

这里有几个需要提示的地方。

1. OtpErlang.jar 里面会访问系统变量 OtpConnection.trace 当它不为 0 时会显示链底层的 debug 信息。在调试时,这个设置就像照妖镜,有啥妖怪问题,都给照出来了。

2. setcookie 很重要。我这里是明确指定 123 作为 cookie ,如果这个 cookie 不匹配(比如,最好用: erl
-setcookie 123 来启动)两端就死活也连不上,尤其是当你没有把上面的 trace 打开的时候,那你就去找去吧。

3. epmd 是 erlang 通讯机制的基础。也就是说,运行的时候,至少需要有一个 epmd 在运行(实际上也只会有一个)。比如说
java client 调用 erlang server ,erlang client 调 java server ,erlang
client 调 erlang server 都很正常的不会有问题。而如果你要 java client 调 java server
的时候,最好先确认一下系统中有 epmd 正在运行。否则就会很邪。而启动一个 epmd 的超简单方法就是打开一个 erlang 的
console ,什么也不干都行。

扩充话提:Java Node 是 Hidden Node,一般启动的 Erlang 程序都运行在非 hidden node 模式下。具体 Hidden Node 的区别超出了本日志的范围,大家自己啃文档吧(其实是我也没看得很透彻,就不误导大家了,哈哈)。

再来个体外话,有了 JInterface 就等于在 Java 和 Erlang 的世界之间架起了一座桥梁。通过这个桥梁能干吗呢?这个问题留给你自己去想。
 
文章来源于http://www.lupaworld.com

试了一下传说中的 JInterface ,使用 OtpErlang.jar 的整个过程其实非常简单,似乎比 JMS 的程序都简单。

首先,我们要用 java 实现的原始 erlang 程序如下,没错,就是巨简单的 echo ,我们的目标是要把它用 java 来改写,不仅写服务端,也要写客户端。

下载: echo_client.erl

-module(echo_client).

 

-export([run/0]).

 

run() ->

    Msg = "Hello Echo!",

    {echo, abc@merlin} ! {self(), Msg},

    io:format("send ~p ~n", [Msg]),

    receive

        Res ->

            io:format("received ~p ~n", [Res])

    end.

下载: echo_server.erl

-module(echo_server).

 

-export([start/0]).

 

start() ->

    register(echo, self()),

    io:format("echo start~n", []),

    loop().

 

loop() ->

    receive

        {Pid, Msg} ->

            io:format("received ~p from ~p~n", [Msg, Pid]),

            Pid ! Msg;

        Any ->

            io:format("received ~p ~n", [Any])

    end,

    loop().

写得并不严密,用了一堆硬编码,主要是个示例,就那么个意思,大家将就着看。

先说一下 JInterface 的一些基本概念。JInterface 的目的是:为 Java 提供一个包,使得 Java
程序在外部可以看起来就像一个标准的 Erlang Node 能以标准的 Erlang 方式与其他的节点进行通讯。它包装了 Erlang
节点之间分布式的通讯协议,编码解码,以及基本的 Erlang 操作,也就是 pid register send receive link
unlink 等等,朴实无华。不过,作为两个语言之间的接口包,有了这些基本功能也就足够了。

根据 Erlang 的目录惯例, JInterface 的 Jar 在
ERLANG_HOME/lib/jinterface-x.x/priv 目录下,名字为 OtpErlang.jar 。注意,必须使用和你当前
Erlang 版本下的包,否则出了什么妖怪问题,别来问我,就算是问我,我也不知道该怎么办。:D 之前一直有一个误解,想当然的以为
JInterface 会用 JNI 什么的来实现,而自从碰过一次以后,对 JNI
这种“难以掌控”的东西总觉得有点畏难,所以,迟迟都没有动手,没想到,竟是纯 Java 实现的一个包。用起来方便,部署起来也漂亮。爽!

闲话休提,直接上代码得了。先是 Client 的代码。

下载: ErlangEchoClient.java

package com.test.erlang;

 

import java.io.IOException;

 

import com.ericsson.otp.erlang.*;

 

public class ErlangEchoClient {

   

    public static void main(String[] args) throws IOException {

       

        String v = System.getProperties().getProperty("OtpConnection.trace");

        System.out.println("OtpConnection.trace="+v);

       

        OtpNode self = new OtpNode("bcd", "123");

       

        System.out.println("node:"+self.node());

        System.out.println("cookie:"+self.cookie());

       

        if (self.ping("abc", 2000)) {

            System.out.println("remote is up");

        } else {

            System.out.println("remote is not up");

            return;

        }

       

        String text = "Hi there";

       

        OtpMbox mbox = self.createMbox();

       

        OtpErlangObject[] msg = new OtpErlangObject[2];

        msg[0] = mbox.self();

        msg[1] = new OtpErlangString(text);

        OtpErlangTuple tuple = new OtpErlangTuple(msg);

 

        mbox.send("echo", "abc", tuple);

       

        System.out.println("send:"+text);

 

        try {

           

            OtpErlangObject reply = mbox.receive();

           

            System.out.println("receive[raw]:"+reply);

           

            if (reply instanceof OtpErlangString) {

                OtpErlangString text2 = (OtpErlangString) reply;

               

                System.out.println("receive[text]:"+text2);

 

            }

        } catch (Exception e) {

            System.out.println("" + e);

        }

    }

 

}

下载: ErlangEchoServer.java

package com.test.erlang;

 

import java.io.IOException;

 

import com.ericsson.otp.erlang.*;

 

public class ErlangEchoServer {

   

    public static void main(String[] args) throws IOException {

       

        String v = System.getProperties().getProperty("OtpConnection.trace");

        System.out.println("OtpConnection.trace="+v);

       

        OtpNode self = new OtpNode("server1", "123");

       

        System.out.println("node:"+self.node());

        System.out.println("cookie:"+self.cookie());

       

        OtpMbox mbox = self.createMbox("echo");

       

        String[] names = self.getNames();

        for(int i=0; i<names.length; i++) System.out.println("name:"+names[i]);

       

        while (true) {

            try {

                OtpErlangObject request = mbox.receive();

               

                System.out.println("receive[raw]:"+request);

               

                if (request instanceof OtpErlangTuple) {

                    OtpErlangTuple t = (OtpErlangTuple) request;

                    OtpErlangPid pid = (OtpErlangPid) (t.elementAt(0));

                    OtpErlangString text = (OtpErlangString) (t.elementAt(1));

                   

                    System.out.println("receive[text]:"+text);

                   

                    OtpErlangString response = text;

                   

                    mbox.send(pid, response);

                }

            } catch (Exception e) {

                System.out.println("" + e);

            }

        }

    }

 

}

这里有几个需要提示的地方。

1. OtpErlang.jar 里面会访问系统变量 OtpConnection.trace 当它不为 0 时会显示链底层的 debug 信息。在调试时,这个设置就像照妖镜,有啥妖怪问题,都给照出来了。

2. setcookie 很重要。我这里是明确指定 123 作为 cookie ,如果这个 cookie 不匹配(比如,最好用: erl
-setcookie 123 来启动)两端就死活也连不上,尤其是当你没有把上面的 trace 打开的时候,那你就去找去吧。

3. epmd 是 erlang 通讯机制的基础。也就是说,运行的时候,至少需要有一个 epmd 在运行(实际上也只会有一个)。比如说
java client 调用 erlang server ,erlang client 调 java server ,erlang
client 调 erlang server 都很正常的不会有问题。而如果你要 java client 调 java server
的时候,最好先确认一下系统中有 epmd 正在运行。否则就会很邪。而启动一个 epmd 的超简单方法就是打开一个 erlang 的
console ,什么也不干都行。

扩充话提:Java Node 是 Hidden Node,一般启动的 Erlang 程序都运行在非 hidden node 模式下。具体 Hidden Node 的区别超出了本日志的范围,大家自己啃文档吧(其实是我也没看得很透彻,就不误导大家了,哈哈)。

再来个体外话,有了 JInterface 就等于在 Java 和 Erlang 的世界之间架起了一座桥梁。通过这个桥梁能干吗呢?这个问题留给你自己去想。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: