如何跨两个Erlang节点发送消息
我的两个Erlang模块中的代码如下所示: 接收者:如何跨两个Erlang节点发送消息,erlang,Erlang,我的两个Erlang模块中的代码如下所示: 接收者: start() -> PID = spawn(?MODULE, message_box, []), PID. message_box() -> sender:start_link(), receive {From, take_this_message} -> From ! "ok thanks !"; {From, fish} ->
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()后显示未收到任何内容。
另外,如何使用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}]}]}
**错误消息:**
=错误报告===2014年7月21日::12:42:44===
使用退出值处理时出错:{unde,[{sender,start_link,[],[]},{receiver,message_box,0,[{file,“receiver.erl”},{line,14}]}
为了能够在两个节点之间交换消息,必须首先启动两个节点(erl-sname foo,erl-sname bar),将它们关联到集群中。这可以使用net\u adm:ping/1函数完成:net\u adm:ping(foo@domain)在条形图节点上。
应返回pong。(如果您得到了pang,那么检查拼写,检查这两个节点是否具有相同的cookie)或net_kernel:connect(foo@domain)应该可以返回
然后,您可以在一个节点上启动接收方进程,并从第二个节点获取其Pid,例如rpc:call(foo@domain,erlang,processs,[])。
将返回在节点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.
在外壳中:
(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>
然后使用语法{name,node}发送消息:sender:init({receiver,bar@W7FRR00423L},记下这封信。
或者,您可以从一个节点创建两个进程,如下所示:
start() ->
PID = spawn(?MODULE, message_box, []),
register(?MODULE,PID),
PID.
(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>
(foo@W7FRR00423L)4> Pid=rpc:call(bar@W7FRR00423L,接收器,开始,[])。
(foo@W7FRR00423L)5> 发送方:init(Pid,fish)。
{好的,“再见,谢谢你的鱼”}
(foo@W7FRR00423L)6>
为了能够在两个节点之间交换消息,必须首先启动两个节点(erl-sname foo,erl-sname bar),将它们关联到集群中。这可以使用net\u adm:ping/1函数完成:net\u adm:ping(foo@domain)在条形图节点上。
应返回pong。(如果您得到了pang,那么检查拼写,检查这两个节点是否具有相同的cookie)或net_kernel:connect(foo@domain)应该可以返回
然后,您可以在一个节点上启动接收方进程,并从第二个节点获取其Pid,例如rpc:call(foo@domain,erlang,processs,[])。
将返回在节点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.
在外壳中:
(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>
然后使用语法{name,node}发送消息:sender:init({receiver,bar@W7FRR00423L},记下这封信。
或者,您可以从一个节点创建两个进程,如下所示:
start() ->
PID = spawn(?MODULE, message_box, []),
register(?MODULE,PID),
PID.
(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>
(foo@W7FRR00423L)4> Pid=rpc:call(bar@W7FRR00423L,接收器,开始,[])。
(foo@W7FRR00423L)5> 发送方:init(Pid,fish)。
{好的,“再见,谢谢你的鱼”}
(foo@W7FRR00423L)6>
除了尝试和错误,还有其他方法来识别接收器的PID吗?通常您使用注册的进程,因此您可以按名称访问它们,如果必须重新启动进程,则名称保持不变。我将使用注册进程发布代码的更新版本。但是您的实现似乎更有用,比如,我想在receiver程序中创建一个指向发送方的链接。我应该将哪些参数传递给spawn\u link/4
?在Erlang中,链接是一个双向连接,由系统管理,确保链接在一起的所有进程(如网格中)将一起消亡。如果您使用spawn_link/4,您将把调用进程与新生成的进程链接起来(例如,shell与接收方);这样做不需要任何参数。我猜您想要的是将发送者链接到接收者,在这种情况下,只需修改send\u receive函数,在开头添加:link(PID),
然后发送者在第一条消息完成后,接收者将立即死亡!除了尝试和错误,还有其他方法来识别接收器的PID吗?通常您使用已注册的进程,因此您可以按名称访问它们,如果必须重新启动进程,则名称保持不变。我将使用注册进程发布代码的更新版本。但是您的实现似乎更有用,比如,我想在receiver程序中创建一个指向发送方的链接。我应该将哪些参数传递给spawn\u link/4
?在Erlang中,链接是一个双向连接,由系统管理,确保链接在一起的所有进程(如网格中)将一起消亡。如果您使用spawn_link/4,您将把调用进程与新生成的进程链接起来(例如,shell与接收方);这样做不需要任何参数。我猜您想要的是将发送者链接到接收者,在这种情况下,只需修改send\u receive函数,在开头添加:link(PID),
然后发送者在第一条消息完成后,接收者将立即死亡!