我是一个 erlang 新手,我正在尝试构建我的第一个消息传递应用程序。我的问题有 2 个部分
当我在终端上打开两个单独的 erlang 控制台而不指定 -sname 属性时,两个 erlang 控制台如何具有相同的进程 pid。它们实际上是相同的过程吗,如何?
Terminal #1
--------------
$> erl
Erlang R15B01 (erts-5.9.1) [source] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.1 (abort with ^G)
1> self().
0.31.0
同样适用于 2 号航站楼
Erlang R15B01 (erts-5.9.1) [source] [smp:4:4] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.9.1 (abort with ^G)
1> self().
0.31.0
两者如何在同一进程上运行。这些是 erlang 进程而不是本机进程吗?
如果我正在构建一个消息传递应用程序,并且我需要某种方法来跟踪每个用户发送的消息的信息。我尝试使用的基本设计是为每个用户创建一个新的聊天客户端。我生成了一个进程来跟踪接收消息的人,从而将他的昵称存储在那里。
同样,我创建了另一个模块,用于跟踪谁发送消息,但在这种情况下,我使用 self() Pid 来跟踪发件人。这发生在chat_client_sender
模块中。
-module(chat_client).
-export([start/0, stop/0, loop/1, login/3, logout/1, send_message/2]).
-define(SERVER, chat_client).
start() ->
message_router:start(),
chat_client_sender:start().
stop() ->
message_router:stop(),
chat_client_sender:stop().
login(Uid, Password, Nickname) ->
io:format("~p My Pid", [self()]),
Pid = spawn(chat_client, loop, [Nickname]),
case message_router:login(Uid, Password, Nickname, Pid) of
{ok, logged_in} ->
chat_client_sender:add_sender(self(), {Uid, Nickname}),
{ok, logged_in};
{error, invalid_uid_or_pwd} ->
{error, invalid}
end.
logout(Uid) ->
case message_router:logout(Uid) of
{ok, logged_out} ->
{ok, logged_out};
ignored ->
ignored;
_Someshit ->
io:format("Some Shit ~p", _Someshit)
end.
send_message(ToUid, MessageBody) ->
chat_client_sender:send_message(ToUid, MessageBody).
loop(Nickname) ->
receive
{print_msg, Messagebody, SenderNickname} ->
io:format("~p: ~p to ~p~n", [SenderNickname, Messagebody, Nickname]),
loop(Nickname);
stop ->
ok
end.
chat_client_sender 模块
-module(chat_client_sender).
-export([start/0, stop/0, add_sender/2, loop/1, get_sender/1, send_message/2]).
-define(SERVER, chat_client_sender).
start() ->
erlang:register(?SERVER, spawn(chat_client_sender, loop, [dict:new()])).
stop() ->
?SERVER ! stop.
add_sender(SenderPid, {Uid, Nickname}) ->
io:format("Adding Sender ~p ~p ~p ~n", [SenderPid, Uid, Nickname]),
?SERVER ! {add_sender, SenderPid, {Uid, Nickname}}.
get_sender(SenderPid) ->
?SERVER ! {get_sender, SenderPid}.
send_message(ToUid, MessageBody) ->
?SERVER ! {send_msg, ToUid, MessageBody}.
loop(MemberPids) ->
receive
{add_sender, SenderPid, {Uid, Nickname}} ->
case dict:find(SenderPid, MemberPids) of
{ok, {Uid, Nickname}} ->
io:format("Pid exists ~n"),
loop(MemberPids);
error ->
loop(dict:store(SenderPid, {Uid, Nickname}, MemberPids))
end;
{send_msg, ToUid, MessageBody, SenderPid} ->
case get_sender(SenderPid, MemberPids) of
{found, _Uid, Nickname} ->
message_router:send_message(ToUid, MessageBody, Nickname),
loop(MemberPids);
not_found ->
not_found,
loop(MemberPids)
end;
{remove_sender, SenderPid} ->
case get_sender(SenderPid, MemberPids) of
{found, _Uid, _Nickname} ->
loop(dict:erase(SenderPid, MemberPids));
not_found ->
ignored,
loop(MemberPids)
end;
{get_sender, SenderPid} ->
case get_sender(SenderPid, MemberPids) of
Any ->
io:format("GET SENDER ~p~n", [Any])
end,
loop(MemberPids);
stop ->
ok
end.
get_sender(SenderPid, MemberPids) ->
case dict:find(SenderPid, MemberPids) of
{ok, {Uid, Nickname}} ->
{found, {Uid, Nickname}};
error ->
not_found
end.
因此,我的应用程序开始add_sender
在我的loop
方法中的子句中失败,该子句存储来自chat_client
.
这是一个例子
chat_client:start().
true
9> chat_client_sender:add_sender(self(), {'sid@abc.com', 'sid'}).
Adding Sender 'sid@abc.com' sid
{add_sender,,{'sid@abc.com',sid}}
10> chat_client_sender:add_sender(self(), {'sid1@abc.com', 'sid1'}).
Adding Sender 'sid1@abc.com' sid1
{add_sender,,{'sid1@abc.com',sid1}}
11>
=ERROR REPORT==== 13-Oct-2012::19:12:42 ===
Error in process with exit value: {{case_clause,{ok,{'sid@abc.com',sid}}},[{chat_client_sender,loop,1,[{file,"chat_client_sender.erl"},{line,25}]}]}
根据我的理解,它应该简单地继续模块中{ok, {Uid, Nickname}}
子句的尾递归。chat_client_sender
...
receive
{add_sender, SenderPid, {Uid, Nickname}} ->
case dict:find(SenderPid, MemberPids) of
{ok, {Uid, Nickname}} ->
io:format("Pid exists ~n"),
loop(MemberPids);
error ->
loop(dict:store(SenderPid, {Uid, Nickname}, MemberPids))
end;
...
我真的很感激一些帮助理解这里发生的事情。此外,如果您能查看我的代码并告诉我更多关于最佳实践和我可以做得更好的事情,我将非常感激。我的代码可在goo.gl/yY4kR 获得
谢谢