簡體   English   中英

從Java發送消息到已注冊的Erlang gen_server

[英]Sending a message from Java to a registered Erlang gen_server

如何從Jinterface Java服務器向全局注冊的gen_server發送消息?

例如,我的gen_server就像這樣啟動:

  start_link ({global, myServerName}, Mod, Args, Options).

mbox.send(“myServerName”,MyMessage)。 不起作用。 沒有消息到達myServerName:handle_info。

一種方法是調用global:send/2作為服務器節點上的RPC。 Java代碼如下所示:

import java.io.IOException;
import com.ericsson.otp.erlang.*;

public class JClient {
    static String server = "server";
    static String global = "myServerName";

    public static void main(String[] args) throws Exception {
        OtpSelf client = new OtpSelf("client", "java");
        OtpPeer peer = new OtpPeer(server);
        OtpConnection conn = client.connect(peer);
        conn.sendRPC("global", "send", new OtpErlangObject[] {
                new OtpErlangAtom(global),
                new OtpErlangTuple(new OtpErlangObject[] {
                        new OtpErlangAtom("publish"),
                        new OtpErlangTuple(new OtpErlangObject[] {
                                new OtpErlangAtom("all"),
                                new OtpErlangString("this is a test")})
                    })});
    }
}

OtpSelf構造函數的第二個參數是Erlang cookie,它必須匹配服務器節點的cookie,如下所示。 該代碼使用sendRPC的方法OtpConnection撥打global:send/2的服務器節點,如果成功,或者如果不是一個錯誤,它返回的全球注冊進程的PID功能上(但在Java代碼不檢查這個)。

服務器可以是一個簡單的gen_server ,如下所示:

-module(svr).
-behaviour(gen_server).

-export([start_link/0, stop/0]).
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
         terminate/2, code_change/3]).

-record(state, {}).

start_link() ->
    gen_server:start_link({global, myServerName}, ?MODULE, [], []).

stop() ->
    gen_server:cast({global, myServerName}, stop).

init([]) ->
    {ok, #state{}}.

handle_call(_Request, _From, State) ->
    {reply, ok, State}.

handle_cast(stop, State) ->
    {stop, normal, State};
handle_cast(_Msg, State) ->
    {noreply, State}.

handle_info({publish, {Topic, Msg}}, State) ->
    io:format("publish for topic ~p: ~p~n", [Topic, Msg]),
    {noreply, State};
handle_info(_Msg, State) ->
    {noreply, State}.

terminate(_Reason, _State) ->
    ok.

code_change(_OldVsn, State, _Extra) ->
    {ok, State}.

請注意,我使用全局名稱myServerName注冊服務器以匹配您在問題中使用的名稱,但實際上我從不使用類似的混合大小寫原子名稱。

要運行服務器,首先啟動一個Erlang shell:

erl -sname server -setcookie java

請注意,cookie與Java代碼中的內容匹配,並且我使用-sname來命名服務器節點; 我根本沒試過長名。

然后,在Erlang shell中運行svr進程:

Erlang R16B03-1 (erts-5.10.4) [source] [64-bit] [smp:8:8] [async-threads:10] [kernel-poll:false] [dtrace]

Eshell V5.10.4  (abort with ^G)
(server@myhost)1> svr:start_link().
{ok,<0.42.0>}

然后,運行Java客戶端,服務器應發出以下消息:

publish for topic all: "this is a test"

這種方法的主要缺點是它必須通過RPC服務器為每個消息。 另一種方法是將RPC發送到global:whereis_name/1以查找已注冊進程的pid,然后使用send而不是sendRPC直接向其發送消息,但缺點是如果全局注冊的進程死亡並重新啟動,Java代碼將需要檢測pid不再有效並重做查找。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM