2011-06-14 137 views
4

我正在寻找erlang的好例子异步使用gen_server处理消息:cast/2。使用gen_server处理Erlang异步消息:cast/2

我见过的OTP SSH模块,它接收到一个请求通过 模块中的一个示例:handle_cast/2,它保持在模块的一个本地队列,后来发回对应于该请求的应答消息,通过明确地向呼叫者发送消息。当我试图阅读它时,我几乎无法跟踪代码,并且无法理解这个想法。

赞赏一段伪代码。

+0

这似乎说明它cast'和'call''之间的差异:http://bytefilia.com/gen_server-synchronous-vs-asynchronous/ – Stratus3D 2014-06-27 19:41:02

回答

5

我相信你指的是ssh_connection_manager模块。

执行gen_server:cast/2时,将在Module:handle_cast/2函数中处理该请求。几件事情要注意这里:

  • handle_cast参数你没有有关发件人的信息,所以你不能 - 除非你发送邮件本身这个信息 - 发回了一些成绩吧。
  • 客户在发出gen_server:cast/2后,不会等待回复。实际上,它甚至不关心消息是否到达(有一些例外)。
  • handle_cast/2,你可以返回一个noreply停止元组,所以没办法返回一个答复那里。

说,你一直在寻找的应该(简化的东西)的代码背后的想法:

  • 初始同步gen_server:call/2
  • 客户端的是传递给服务器并保存到其状态(实际上,似乎用该参数创建了一个额外的过程)。这个技巧在你不能计算handle_call时的返回值时很有用。
  • 在这一点上,你有两种可能,这取决于如果你需要更多的信息来计算从其他客户端(A)你的结果或来自同一客户(B):

    • A.返回类似{ noreply NewState}在handle_call中。这将使您有可能在客户仍然持有的情况下处理其他请求。当结果准备就绪时,您可以使用gen_server:reply()将其发送回客户端。
    • B.将{reply,ok,State}返回给客户端。客户端将继续执行,也许执行一系列cast/2。然后,客户会用新的gen_server:call/2询问最终结果。
+0

感谢您的澄清。现在我记得代码的流程。我应该写这个ssh本身就是一种行为。 – jj1bdx 2011-06-15 12:45:17

+0

当你的意思是客户端仍在持有时,你的意思是客户端被阻止并且无法继续执行?有没有办法阻止它?可以得到延期回复吗?或者最好是像jj1bdx说的那样创建一个自定义行为? – Ale 2011-06-29 12:55:31

+0

我认为这可能有助于http://www.trapexit.org/Building_Non_Blocking_Erlang_apps – Ale 2011-06-29 13:05:06

4

通常情况下,您不希望发送剧组时直接回复,否则您会使用gen_server:call。

一个真实世界的例子,我有一个gen_server来处理一些“通道”,并且有很多用来追加通道名称到错误记录。频道名称存储在gen_server的状态中。为了不耽误谁想要登录我不使用“获取名称”错误的过程中同步调用来获取名称的预先准备,但发送的邮件,用石膏:

error(Pid, Tags) -> 
    gen_server:cast(Pid, {log, error_report, Tags}). 

warning(Pid, Tags) -> 
    gen_server:cast(Pid, {log, warning_report, Tags}). 

info(Pid, Tags) -> 
    gen_server:cast(Pid, {log, info_report, Tags}). 

演员被处理在一个非常简单的处理程序中,不会返回。

handle_cast({log, Report, Tags}, #state{name=Name}=State) -> 
    error_logger:Report([{chan, Name} | Tags]), 
    {noreply, State}; 

如果你有异步消息发回,这是完全独立的施法的处理。您无论如何都需要知道在哪里发送这些消息,您必须以某种方式将这些消息存储在State中,或者您使用的是固定名称。

通常情况下,你不应该只是发送一条消息,而是调用接收处理模块的函数(这可能是另一个强制转换或简单的消息发送)。

+0

感谢您的解释。 – jj1bdx 2011-06-15 12:46:32