如何将消息从 Jinterface Java 服务器发送到全局注册的 gen_server?
例如,我的 gen_server 是这样启动的:
start_link ({global, myServerName}, Mod, Args, Options).
mbox.send("myServerName", MyMessage)。不起作用。没有消息到达 myServerName:handle_info。
如何将消息从 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
命名服务器节点的内容相匹配;我根本没有尝试过长名字。
然后,svr
在 Erlang shell 中运行该进程:
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 不再有效并重做查找。