erlang - erlang将消息从服务器传递到不同的节点
问题描述
我正在尝试让一个简单的 erlang 服务器在我尝试注册服务器的地方工作,将消息传递给服务器,该服务器应该在不同的节点上注册并创建 2 个进程,但我收到了这个错误:
{badarg,[{erlang,register,[printer1,<12172.86.0>],[]},
{testerl,server,1,[{file,"testerl.erl"},{line,13}]}]}
我的代码:
-module(testerl).
-export([start_server/1,
server/1,
printer/0
]).
server(Node_1) ->
receive
finished ->
exit(normal);
{Message} ->
register(printer1, spawn(Node_1, testerl, printer, [])),
register(printer2, spawn(Node_1, testerl, printer, [])),
{printer1, Node_1} ! {Message},
{printer2, Node_1} ! {Message},
server(Node_1)
end.
printer() ->
receive
finished->
exit(normal);
{Message} ->
io:format("printer received msg ~p~n", [Message]),
server ! finished
end.
start_server(Node_1) ->
register(server, spawn(testerl, server, [Node_1])).
我可以使用 erl -sname [name] 启动 2 个节点,使用另一个节点的名称启动服务器,但是当我尝试使用服务器传递消息时!“一些消息”它崩溃了。我在这里做错了什么?我如何注册一个进程并调用它以便它在另一台机器上执行?
解决方案
您收到 badarg 错误是因为您尝试通过 erlang:register/2 注册非本地 Pid。
文档(http://erlang.org/doc/man/erlang.html)表明:
badarg
If PidOrPort is not an existing local process or port.
spawn(Node_1,...) 的结果是另一个节点(即 Node_1)上的 Pid。如果你想注册一个非本地的 Pid,你可以使用 global:register_name。
所以:
-module(testerl).
-export([start_server/1,
server/1,
printer/0
]).
server(Node_1) ->
receive
finished ->
exit(normal);
{Message} ->
global:register_name(printer1, spawn(Node_1, testerl, printer, [])),
global:register_name(printer2, spawn(Node_1, testerl, printer, [])),
global:send(printer1, {Message}),
global:send(printer2, {Message}),
server(Node_1)
end.
printer() ->
receive
finished->
exit(normal);
{Message} ->
io:format("printer received msg ~p~n", [Message]),
global:send(server, finished)
end.
start_server(Node_1) ->
global:register_name(server, spawn(testerl, server, [Node_1])).
运行这个,我得到:
(node1@f0189805e911)59> testerl:start_server('node2@f0189805e911').
(node1@f0189805e911)60> yes
(node1@f0189805e911)61> global:send(server,{test}).
(node1@f0189805e911)62> printer received msg test
(node1@f0189805e911)63> printer received msg test
当然,不需要使用注册进程:
-module(testerl).
-export([start_server/1,
server/3,
printer/1
]).
server(Node_1, P1, P2) ->
receive
finished ->
exit(normal);
{Message} ->
P1 ! {Message},
P2 ! {Message},
server(Node_1, P1, P2)
end.
printer(ServerPid) ->
receive
finished->
exit(normal);
{Message} ->
io:format("printer received msg ~p~n", [Message]),
ServerPid ! finished
end.
start_server(Node_1) ->
P1 = spawn(Node_1, testerl, printer, [self()]),
P2 = spawn(Node_1, testerl, printer, [self()]),
spawn(testerl, server, [Node_1, P1, P2]).
运行这个:
(node1@f0189805e911)14> Pid = testerl:start_server('node2@f0189805e911').
<0.117.0>
(node1@f0189805e911)15> Pid ! {test}.
{test}
printer received msg test
printer received msg test
(node1@f0189805e911)16>
推荐阅读
- javascript - 如何在 React Native 上导入和使用 .jar 文件
- c# - 我需要在 Microsoft Exchange 服务代码中设置 Accept/Decline EmailMessage 对象
- c# - 反序列化 JSON 以适应模型
- elasticsearch - 使用 Nest 搜索未产生预期结果
- ios - iPhone has denied the launch request
- c# - PrintPreviewDialog 调用 PrintDocument.PrintPage 中的字符串长度限制
- python-3.x - 有没有办法将使用 PyPDF2 合并的 pdf 的大小保持在最小或在合并后减小大小?
- r - 带有 `stopifnot()` 和 `testit::assert()` 的管道
- android - React Native Picker: onValueChange triggers unintended onValueChange for other pickers
- angular - NgRx: Get data from store but it's undefined