Erlang:在查询和响应中使用`Ref`

时间:2017-05-23 05:37:14

标签: erlang

我正在阅读LearnYouSomeErlang并找到以下代码:

我的问题是为什么我们在Ref函数中需要event。 我认为给出的原因是Ref就像request-id。

如果我向dont_give_crap发送多个请求,当我收到回复时,Ref作为回应告诉我它是哪个ID。

但是,由于event正在阻止,我只发送一个请求,在哪种情况下,我能够将同一进程的多个请求发送到dont_give_crap process吗? Ref的目的是什么?

-module(cat_fsm).
-export([start/0, event/2]).

start() ->
    spawn(fun() -> dont_give_crap() end).

event(Pid, Event) ->
    Ref = make_ref(), % won't care for monitors here
    Pid ! {self(), Ref, Event},
    receive
    {Ref, Msg} -> {ok, Msg}
    after 5000 ->
        {error, timeout}
    end.

dont_give_crap() ->
    receive
    {Pid, Ref, _Msg} -> Pid ! {Ref, meh};
    _ -> ok
    end,
    io:format("Switching to 'dont_give_crap' state~n"),
    dont_give_crap().

2 个答案:

答案 0 :(得分:7)

  

我的问题是为什么我们需要Ref

这就像验证码。如果有进程的Pid,任何其他进程都可以向您的进程发送消息。

  

我认为给出的理由是Ref就像request-id。

Ref更像是回复ID。这是进程期望在回复中收到的id。如果你写:

receive
    Msg ->  %%do something
end

然后发送到您的进程邮箱的任何邮件都将匹配该模式,您将无法知道它来自何处。如果你写:

receive
    {Pid, Msg} ->  %%do something
end

您仍然无法确定该消息来自进程Pid。您的另一个进程可能有多个Pid它正在回复并意外地使用了错误的Pid来处理该消息。

但是如果你发送一个参与你的处理Pid的请求,那么处理Pid可以回复一条包含收到的Ref和它的Pid的消息,然后你可以从你的邮箱中提取包含Ref和发件人的Pid的消息并确保它来自进程Pid(实际上,进程Pid可以将Ref发送到其他进程,因此您仍然无法确定)。

如果您的erlang应用程序有1,000个进程相互发送100条消息,那么如果您只验证了Pid回复的来源,则可能更容易出错。

编辑:我刚刚阅读有关gen_udp和套接字的内容,结果发现有些服务器可以复制回复。假设发生这种情况,客户端从邮箱中提取第一个回复,如下所示:

receive
    {Pid, Msg1} -> Msg1
end

然后客户端发送第二个请求并等待回复:

receive
    {Pid, Msg2} -> Msg2
end

那么,该模式将提取对第一个请求的重复回复 - 而不是对第二个请求的回复。但是如果一个唯一的Ref并且已经同时发送了第一个和第二个请求:

Pid = ...,
Ref1 = ...,
Pid ! {self(), Ref1, Msg1},
receive
    {Pid, Ref1, Reply1} -> Reply1
end,

Ref2 = ...,
Pid ! {self(), Ref2, Msg2},
receive
    {Pid, Ref2, Reply2} -> Reply2
end.

然后第二次接收与第一次请求的重复回复不匹配。这是一个很好地使用Ref。

的具体例子

答案 1 :(得分:1)

  1. 在查询和回复中使用Ref
  2. 每个进程都有自己的邮箱,如家中的邮箱。邮箱是向任何进程发送任何请求的入口点。

    根据您的代码,您希望从特定流程返回响应。所以 您必须在邮箱中提取邮件的位置指定预期的进程pid。

    1. 我是否可以将同一进程的多个请求发送到dont_give_crap进程? Ref?
    2. 的目的是什么?

      这是不可能的。从进程A向进程B发送多个请求.A - > B,即如果A向B发送阻塞消息,则A在块中,意味着它不接受来自任何其他进程的任何其他消息。

      每条消息因消息结构的模式匹配而不同

相关问题