我的两个Erlang模块中的代码如下:
接收者:
start() ->
PID = spawn(?MODULE, message_box, []),
PID.
message_box() ->
sender:start_link(),
receive
{From, take_this_message} ->
From ! "ok thanks !";
{From, fish} ->
From ! "So long and thanks for all the fish";
_ ->
io:format("Received Nothing~n")
end.
发件人:
-module(sender).
-compile(export_all).
start_link() ->
PID = spawn_link(?MODULE, init, [self()]),
PID.
init(PID) ->
PID ! {self(), "Wassup!"}.
我希望接收器在调用start_link()后显示Received Nothing。 另外,如何使用shell或其他方式检查模块/进程在运行时收到的消息?
**ERROR MESSAGE:**
=ERROR REPORT==== 21-Jul-2014::12:42:44 ===
Error in process <0.40.0> with exit value: {undef,[{sender,start_link,[],[]},{receiver,message_box,0,[{file,"receiver.erl"},{line,14}]}]}
答案 0 :(得分:3)
为了能够跨2个节点交换消息,您必须首先启动2个节点(erl -sname foo,erl -sname bar)将它们关联到群集中。这可以使用net_adm:ping / 1函数来完成:net_adm:ping(foo@domain) on the bar node.
应该返回你的pong。 (如果你得到剧痛,然后拼写拼写,检查2个节点是否有相同的cookie),或者net_kernel:connect(foo @ domain)应该返回ok。
然后,您可以在一个节点上启动接收器进程,并从第二个节点获取其Pid,例如rpc:call(foo@domain,erlang,processes,[]).
将返回在节点foo上运行的所有进程的列表。
然后,您可以在第二个节点上运行send函数,并在shell消息队列中获取返回的消息。
这是因为send函数使用self()来给pid提供返回答案的位置,并且它在shell进程中运行(没有产生新进程)。
如果在没有更改的情况下生成函数,则返回消息将丢失,因为在发送第一条消息后进程将立即死亡。你需要修改它,例如:
-module(sender).
-compile(export_all).
init(PID,Mess) ->
spawn(?MODULE,send_receive,[PID,Mess]).
send_receive(PID,Mess) ->
PID ! {self(), Mess},
R = receive
M -> {ok,M}
after 5000 -> {error,"no answer!"}
end,
io:format("~p~n",[R]).
-module (receiver).
-compile(export_all).
start() ->
PID = spawn(?MODULE, message_box, []),
PID.
message_box() ->
receive
{From, take_this_message} ->
From ! "ok thanks !";
{From, fish} ->
From ! "So long and thanks for all the fish";
_ ->
io:format("Received Nothing~n")
end.
shell中的:
(foo@W7FRR00423L)3> receiver:start().
<0.50.0>
Received Nothing
(foo@W7FRR00423L)4> receiver:start().
<0.53.0>
(foo@W7FRR00423L)5> receiver:start().
<0.55.0>
Received Nothing
(foo@W7FRR00423L)6>
(bar@W7FRR00423L)1> net_kernel:connect(foo@W7FRR00423L).
true
(bar@W7FRR00423L)2> nodes().
[foo@W7FRR00423L]
(bar@W7FRR00423L)3> rpc:call(foo@W7FRR00423L,erlang,processes,[]).
[<6075.0.0>,<6075.3.0>,<6075.6.0>,<6075.7.0>,<6075.9.0>,
<6075.10.0>,<6075.11.0>,<6075.12.0>,<6075.13.0>,<6075.14.0>,
<6075.15.0>,<6075.16.0>,<6075.17.0>,<6075.18.0>,<6075.19.0>,
<6075.20.0>,<6075.21.0>,<6075.22.0>,<6075.23.0>,<6075.24.0>,
<6075.25.0>,<6075.26.0>,<6075.27.0>,<6075.28.0>,<6075.29.0>,
<6075.30.0>,<6075.31.0>,<6075.32.0>,<6075.33.0>|...]
(bar@W7FRR00423L)4> sender:init(pid(6075,50,0),take_this_message).
<0.55.0>
{error,"no answer!"}
(bar@W7FRR00423L)5> sender:init(pid(6075,53,0),take_this_message).
<0.57.0>
{ok,"ok thanks !"}
(bar@W7FRR00423L)6> sender:init(pid(6075,55,0),"Wassup!").
<0.59.0>
{error,"no answer!"}
(bar@W7FRR00423L)7>
[编辑]
正如评论中所述,当独立创建2个进程时,通常会通过注册进程(在单个节点上也是如此),例如,您可以像这样修改接收器:
start() ->
PID = spawn(?MODULE, message_box, []),
register(?MODULE,PID),
PID.
然后使用语法{name,node}发送消息以发送消息:sender:init({receiver,bar@W7FRR00423L},take_this_message).
或者您可以从一个节点创建2个进程,如下所示:
(foo@W7FRR00423L)4> Pid = rpc:call(bar@W7FRR00423L,receiver,start,[]).
<5974.54.0>
(foo@W7FRR00423L)5> sender:init(Pid,fish).
<0.50.0>
{ok,"So long and thanks for all the fish"}
(foo@W7FRR00423L)6>