gpt4 book ai didi

erlang - 难以理解 Erlang Gen_Server 架构

转载 作者:行者123 更新时间:2023-12-04 22:28:30 28 4
gpt4 key购买 nike

我正处于学习 Erlang 的早期阶段,我需要一些进一步的帮助。不确定这是否会得到任何阳光,但它就在这里......我正在寻找关于该示例如何工作的流程图。

示例代码:
https://github.com/erlware/Erlang-and-OTP-in-Action-Source/blob/master/chapter_03/tr_server.erl

让我解释一下我的问题...

1> tr_server:start_link().

我理解这一点,它调用 start_link(?DEFAULT_PORT) 来调用 gen_server:start_link - 这实际上得到了对 tr_server(?MODULE) init([Port]) 的调用。
init([Port]) ->
{ok, LSock} = gen_tcp:listen(Port, [{active, true}]),
{ok, #state{port = Port, lsock = LSock}, 0}.

这也是理解的。您将数据发送到服务器, gen_server:handle_info/2 得到处理,因此调用 ?MODULE:handle_info/2 - 这是一个案例,并且由于我们在 ?MODULE:init 中返回了超时,它将与 handle_info(超时,#state{lsock = LSock} = 状态)。

好的,这是有道理的。

这就是我开始对 Erlang 的流程感到困惑的地方

几天来,我一直在阅读这方面的在线资源(包括 Erlang-and-OTP-in-action)——这个例子的来源——还有: http://learnyousomeerlang.com/clients-and-servers

我不确定 Erlang 服务器的流程是如何工作的。我的理解是,发送到服务器的任何消息都将由 gen_server:handle_info/2 处理,如果它们超出范围 - 意味着如果它们没有配置或匹配任何其他 gen_server:handle_call/3?这意味着,任何 TCP 数据都由 gen_server:handle_info/2 自动处理——它会回调 ?MODULE:handle_info?

我不明白的是handle_call、handle_cast如何以及在哪里进入服务器架构——我也不了解服务器从客户端到服务器架构的流程(直到我感到困惑)。我认为这对于说明流程图非常重要,就像电路图一样。

这是主要问题:
当客户端发送以下内容时,服务器的流程是什么:
lists:reverse([1,2,3]).

在纯文本中,最好获得流程图以了解其工作原理。从文本和示例中,它不是很清楚它是如何工作的。目前还不清楚为什么我们需要:
get_count() ->
gen_server:call(?SERVER, get_count).

stop() ->
gen_server:cast(?SERVER, stop).

我很感激任何答案,我知道解释起来可能很累!如有语法错误,请见谅!

最佳答案

在数据来自 tcp 端口和服务器通过 handle_info 回调处理此情况的情况下,您似乎对流程有了很好的了解。这是一种客户端/服务器交互,在 Erlang 代码和连接到端口的一些外部客户端之间。但是在 Erlang 系统中,Erlang 进程之间也存在客户端/服务器关系,双方都在运行 Erlang 代码。 (即使只是 gen_server 进程和 Erlang 命令 shell 进程。)

当您使用 gen_server:call/cast 客户端函数时,它们会以您从未见过的方式包装您的消息,但接收的 gen_server 进程会识别这一点并使用它对消息进行分类,然后将解包的消息传递给相应的 handle_call/handle_cast。除此之外,流程与 tcp 端口上的传入数据相同:在这两种情况下,它只是到服务器的异步消息,被接收并分派(dispatch)到正确的函数。同时在客户端, gen_server:call() 函数将等待回复(发送者的 Pid 包含在包装器中),而 gen_server:cast() 立即继续。

这些实际上只是便利功能。原则上, gen_server 可能只有一个回调来处理各种消息,让你来编码它是调用还是强制转换以及如何使用react。但是通过提供这些库函数并为您分类消息,它可以降低将调用视为强制转换或反之亦然的风险,或者将带外消息与正确的调用/强制转换混淆。流程在所有情况下都是相同的:客户端 -> 服务器 -> 回调 [ -> 服务器回复 -> 客户端 ]。

因此,您可以使用 ?SERVER !
{get_count, self()}
来实现 get_count() 函数。 ,在您的 handle_info() 回调中而不是在 handle_call() 中处理该消息。 (只是不要忘记将回复发送回消息中包含的 Pid,否则客户端将永远卡住。)

或者您可以完全跳过实现 get_count() 之类的用户 API 函数,并告诉您的用户只需将 {get_count, self()} 发送到服务器进程并等待回复(其形状也必须记录在案)。但是,您以后无法更改这些消息在后台的外观细节。 gen_server:call/cast 函数可帮助您隐藏这些杂乱的实现细节,并降低您搞砸客户端/服务器通信的可能性。

希望这可以帮助。

关于erlang - 难以理解 Erlang Gen_Server 架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43982822/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com